diff options
Diffstat (limited to 'statusbar_panel.js')
-rw-r--r-- | statusbar_panel.js | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/statusbar_panel.js b/statusbar_panel.js new file mode 100644 index 0000000..6e68e6c --- /dev/null +++ b/statusbar_panel.js @@ -0,0 +1,151 @@ +let INFO = //{{{
+<plugin name="statusbar panel" version="0.1"
+ href="http://github.com/vimpr/vimperator-plugins/raw/master/click_statusbarpanel.js"
+ summary="Click statusbar panel"
+ lang="ja"
+ xmlns="http://vimperator.org/namespaces/liberator">
+ <author href="http://d.hatena.ne.jp/wlt/" email="wltlain@gmail.com">wlt</author>
+ <license href="http://www.opensource.org/licenses/mit-license.php">MIT License</license>
+ <project name="vimperator" minVersion="2.3.1"/>
+ <p>
+ ステータスバー(アドオンバー)にあるパネル(アイコン)をクリックするコマンドを提供します。
+ </p>
+ <item>
+ <tags>:statusbar</tags>
+ <spec>:statusbar <oa>-button=<a>l | m | r</a></oa> <oa>-double-click</oa> <a>panel-id</a></spec>
+ <description>
+ <p>
+ <a>panel-id</a>で指定するID属性を持つステータスバーパネル(アイコン)をクリックします。
+ クリックするボタンは<oa>-button=</oa>で指定できます:
+ </p>
+ <dl>
+ <dt>l</dt>
+ <dd>左ボタン(デフォルト)</dd>
+ <dt>m</dt>
+ <dd>中ボタン(スクロールボタン)</dd>
+ <dt>r</dt>
+ <dd>右ボタン</dd>
+ </dl>
+ <p><oa>-double-click</oa>を指定するとダブルクリックになります。</p>
+ </description>
+ </item>
+</plugin>;
+//}}}
+
+let MOUSE_BUTTON_LEFT = 0;
+let MOUSE_BUTTON_MIDDLE = 1;
+let MOUSE_BUTTON_RIGHT = 2;
+
+function getImages(panel) {
+ var images = [];
+ // 普通の子孫要素のimage要素探索
+ for (let [k, node] in Iterator(panel.getElementsByTagName('image'))) images.push(node);
+ // 匿名コンテントの子孫要素のimage要素探索
+ var anonymousNodes = document.getAnonymousNodes(panel);
+ for (let [k, anonymousNode] in Iterator(anonymousNodes)) {
+ let node;
+ let result = document.evaluate('descendant-or-self::xul:image', anonymousNode, function() XUL.uri, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+ while ((node = result.iterateNext())) images.push(node);
+ }
+
+ return images;
+}
+
+function makeIcon(panel) {
+ var icon = <image xmlns={XUL.uri}/>;
+ var image = getImages(panel)[0];
+
+ if (image) {
+ let style = window.getComputedStyle(image, null);
+ let src = image.src || style.listStyleImage.replace(/^url\("(.+)"\)$/, '$1');
+ if (src != '') {
+ icon.@style = 'list-style-image: url("' + src + '");' +
+ '-moz-image-region: ' + style.MozImageRegion;
+ }
+ }
+ return icon;
+}
+
+function generateStatusbarpaneIDlList(filter) {
+ var panels = document.getElementsByTagNameNS(XUL.uri, 'statusbarpanel');
+ for ([k, p] in Iterator(panels)) {
+ if (p.hidden != true) {
+ yield {
+ text: p.id,
+ desc: 'statusbarpanel',
+ icon: makeIcon(p)
+ };
+ }
+ }
+}
+
+function createAndDispatchEvent(target, type, detail, screenX, screenY, button) {
+ var ev = document.createEvent('MouseEvents');
+ ev.initMouseEvent(type, true, true, window, detail, screenX, screenY, 0, 0, false, false, false, false, button, null);
+ target.dispatchEvent(ev);
+}
+
+function clickStatusIcon(panel, button, doubleClick) {
+ var target = getImages(panel)[0] || panel;
+ if (!target) return;
+ var x = target.boxObject.screenX;
+ var y = target.boxObject.screenY;
+ x += target.clientWidth / 2;
+ y += target.clientHeight / 2;
+
+ // イベントの発生順序 http://www.quirksmode.org/dom/events/click.html
+ createAndDispatchEvent(target, 'mousedown', 0, x, y, button);
+ createAndDispatchEvent(target, 'mouseup', 0, x, y, button);
+ createAndDispatchEvent(target, 'click', 1, x, y, button);
+
+ if (doubleClick) {
+ createAndDispatchEvent(target, 'mousedown', 0, x, y, button);
+ createAndDispatchEvent(target, 'mouseup', 0, x, y, button);
+ createAndDispatchEvent(target, 'click', 1, x, y, button);
+ createAndDispatchEvent(target, 'dblclick', 2, x, y, button);
+ } else if (button == MOUSE_BUTTON_RIGHT) {
+ createAndDispatchEvent(target, 'contextmenu', 1, x, y, button);
+ }
+}
+
+commands.addUserCommand(['statusbar'],'click statusbar panel',
+ function(args) {
+ var id = args[0];
+ var panel = document.getElementById(id);
+ if (!panel) {
+ liberator.echoerr('No such statusbar panel: ' + id);
+ return;
+ }
+ var button = MOUSE_BUTTON_LEFT;
+ switch (args['-button']) {
+ case 'm': button = MOUSE_BUTTON_MIDDLE; break;
+ case 'r': button = MOUSE_BUTTON_RIGHT; break;
+ case 'l': default: button = MOUSE_BUTTON_LEFT; break;
+ }
+ clickStatusIcon(panel, button, args['-double-click']);
+ }, {
+ argCount: '1',
+ options: [
+ [['-button', '-b'], commands.OPTION_STRING,
+ function(arg) /^[lmr]$/.test(arg),
+ [['l', 'Left click (default)'],
+ ['m', 'Middle click'],
+ ['r', 'Right click']]],
+ [['-double-click', '-d'], commands.OPTION_NOARG]
+ ],
+ completer: function(context, args) {
+ var arg = args[0];
+ context.anchored = false;
+ context.title = ['Panel ID'];
+ context.keys = { text: 'text', description: 'desc', icon: 'icon' };
+ context.compare = CompletionContext.Sort.unsorted;
+ context.process = [function (item, text) {
+ return <><span highlight="CompIcon">{item.icon ? item.icon : <></>}</span><span class="td-strut"/>{text}</>
+ }];
+
+ var list = generateStatusbarpaneIDlList(arg);
+ context.completions = list;
+ }
+ }, true);
+
+// vim: set sw=4 ts=4 et fdm=marker :
|