aboutsummaryrefslogtreecommitdiffstats
path: root/bufferecho.js
AgeCommit message (Collapse)Author
2008-11-27follow CVS HEAD (fix: command argument and completer) and use util.htmlEscapeteramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@25155 d0d07461-0603-4401-acd4-de1884942a52
2008-11-19follow CVS Headteramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@24351 d0d07461-0603-4401-acd4-de1884942a52
2008-10-15namespaceの省略(vimperator CVS headと旧版との互換性維持のため)teramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@21395 d0d07461-0603-4401-acd4-de1884942a52
2008-09-21コマンド文字をHTMLエスケープteramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@19662 d0d07461-0603-4401-acd4-de1884942a52
2008-09-21fix: indentteramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@19659 d0d07461-0603-4401-acd4-de1884942a52
2008-09-20newteramako
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@19658 d0d07461-0603-4401-acd4-de1884942a52
n96' href='#n96'>96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
let INFO = //{{{
<plugin name="statusbar panel" version="0.1"
        href="https://github.com/vimpr/vimperator-plugins/raw/master/statusbar_panel.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>:statusbarpanel</tags>
        <spec>:statusbarpanel <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(['statusbarpanel'],'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 :