/** * ==VimperatorPlugin== * @name moreqmarks.js * @description add feature(record position, stack, queue) to QuickMarks * @description-ja QuickMarksに機能追加(位置の記憶、qmarksとは別のスタックとキュー追加) * @author hogelog * @version 0.05 * ==/VimperatorPlugin== * * MAPPINGS: * "gj" -> Jump to QuickMark for current URL * "gd" -> Delete QuickMark for current URL * "gs" -> Push QuickMarkStack for current URL * "gS" -> Pop QuickMarkStack and Jump * "gq" -> Queue QuickMarkQueue for current URL * "gQ" -> Dequeue QuickMarkStack and Jump * * COMMANDS: * :qmarkpu[sh], :qmpu[sh] -> Push QuickMarkStack for current URL * :qmarkpo[p], :qmpo[p] -> Pop QuickMarkStack and Jump * :stackli[st], :stli[st] -> List QuickMarkStack * :qmarkqu[eue], :qmqu[eue] -> Queue QuickMarkQueue for current URL * :qmarkde[que], :qmde[que] -> Dequeue QuickMarkStack and Jump * :queueli[st], :quli[st] -> List QuickMarkQueue * */ (function(){ var use_position = true; var use_default_data = true; var qmarks = {}; var qmark_stack = []; var qmark_queue = []; // TODO: move to a storage module var savedMarks = liberator.modules.options.getPref("extensions.vimperator.moreqmarks", "").split("\n"); var savedMarkStack = liberator.modules.options.getPref("extensions.vimperator.moreqmarkstack", "").split("\n"); var savedMarkQueue = liberator.modules.options.getPref("extensions.vimperator.moreqmarkqueue", "").split("\n"); // load the saved quickmarks -- TODO: change to sqlite if(use_default_data) { var defaultMarks = liberator.modules.options.getPref("extensions.vimperator.quickmarks", "").split("\n"); for (var i = 0; i < defaultMarks.length - 1; i += 2) { var url = defaultMarks[i+1]; qmarks[defaultMarks[i]] = {url: url, x: 0, y: 0}; } } for (var i = 0; i < savedMarks.length - 1; i += 4) { var url = savedMarks[i+1]; var x = savedMarks[i+2]; var y = savedMarks[i+3]; qmarks[savedMarks[i]] = {url: url, x: x, y:y}; } for (var i = 0; i < savedMarkStack.length - 1; i += 3) { var url = savedMarkStack[i]; var x = savedMarkStack[i+1]; var y = savedMarkStack[i+2]; qmark_stack.push({url: url, x: x, y:y}); } for (var i = 0; i < savedMarkQueue.length - 1; i += 3) { var url = savedMarkQueue[i]; var x = savedMarkQueue[i+1]; var y = savedMarkQueue[i+2]; qmark_queue.unshift({url: url, x: x, y:y}); } function add_qmark(qmark, item, target) { switch(target) { case "stack": qmark_stack.push(item); break; case "queue": qmark_queue.unshift(item); break; case "mark": default: qmarks[qmark] = item; break; } } function get_qmark(qmark, target) { switch(target) { case "stack": return qmark_stack[qmark_stack.length-1]; case "queue": return item = qmark_queue[qmark_queue.length-1]; case "mark": default: return qmarks[qmark]; } } function get_qmarks(target) { var marks = []; // TODO: should we sort these in a-zA-Z0-9 order? var count = 0; var list; switch(target) { case "stack": list = qmark_stack; break; case "queue": list = qmark_queue; break; case "mark": default: list = qmarks; break; } for (var mark in list) { marks.push([mark, list[mark].url, list[mark].x, list[mark].y]); } marks.sort(); return marks; } function list_qmarks(marks) { if(use_position) { var list = ":" + liberator.modules.util.escapeHTML(liberator.modules.commandline.command) + "
" + ""; for (var i = 0; i < marks.length; i++) { list += "" + "" + "" + "" + "" + ""; } list += "
marklinecolfile
" + marks[i][0] + "" + Math.round(marks[i][2] * 100) + "%" + Math.round(marks[i][3] * 100) + "%" + liberator.modules.util.escapeHTML(marks[i][1]) + "
"; return list; } else { var list = ":" + liberator.modules.util.escapeHTML(liberator.modules.commandline.command) + "
" + ""; for (var i = 0; i < marks.length; i++) { list += ""; } list += "
QuickMarkURL
" + marks[i][0] + "" + liberator.modules.util.escapeHTML(marks[i][1]) + "
"; return list; } } function jump_item(item, where, find) { var url = item.url; var x = item.x; var y = item.y; if (url) { if(find) { for (let [number, browser] in Iterator(liberator.modules.tabs.browsers)) { var marked_url = browser.contentDocument.location.href; if(marked_url == url) { liberator.modules.tabs.select(number, false); var win = getBrowser().selectedTab.linkedBrowser.contentWindow; if(use_position) { if(x!=0 || y!=0) { win.scrollTo(x*win.scrollMaxX, y*win.scrollMaxY); } } return true; } } } var tab = open_url(url, where); if(tab) { var win = tab.linkedBrowser.contentWindow; if(use_position) { if(x!=0 || y!=0) { // scrollMaxX and scrollMaxY are 0 before construct content // But small document(scrollMaxX = 0 and scrollMaxY = 0) is marked, // maybe f is run forever. var f = function() { if(win.scrollMaxX==0 && win.scrollMaxY==0) { setTimeout(f, 100); } else { win.scrollTo(x*win.scrollMaxX, y*win.scrollMaxY); } } f(); } } } return true; } return false; } function save_qmarks(target) { switch(target) { case "stack": var savedQuickMarkStack = ""; for (var mark in qmark_stack) { savedQuickMarkStack += qmark_stack[mark].url + "\n"; savedQuickMarkStack += qmark_stack[mark].x + "\n"; savedQuickMarkStack += qmark_stack[mark].y + "\n"; } liberator.modules.options.setPref("extensions.vimperator.moreqmarkstack", savedQuickMarkStack); break; case "queue": var savedQuickMarkQueue = ""; for (var mark in qmark_queue) { savedQuickMarkQueue += qmark_queue[mark].url + "\n"; savedQuickMarkQueue += qmark_queue[mark].x + "\n"; savedQuickMarkQueue += qmark_queue[mark].y + "\n"; } liberator.modules.options.setPref("extensions.vimperator.moreqmarkqueue", savedQuickMarkQueue); break; case "mark": default: var savedQuickMarks = ""; for (var mark in qmarks) { savedQuickMarks += mark + "\n"; savedQuickMarks += qmarks[mark].url + "\n"; savedQuickMarks += qmarks[mark].x + "\n"; savedQuickMarks += qmarks[mark].y + "\n"; } liberator.modules.options.setPref("extensions.vimperator.moreqmarks", savedQuickMarks); if(use_default_data) { var savedQuickMarks = ""; for (var mark in qmarks) { savedQuickMarks += mark + "\n"; savedQuickMarks += qmarks[mark].url + "\n"; } liberator.modules.options.setPref("extensions.vimperator.quickmarks", savedQuickMarks); } break; } } function open_url(url, where) { if (liberator.forceNewTab && liberator.has("tabs")) where = liberator.NEW_TAB; else if (!where || !liberator.has("tabs")) where = liberator.CURRENT_TAB; var whichwindow = window; // decide where to load the first url switch (where) { case liberator.CURRENT_TAB: getBrowser().loadURIWithFlags(url, null, null, null, null); return getBrowser().selectedTab; case liberator.NEW_TAB: return getBrowser().selectedTab = getBrowser().addTab(url, null, null, null); case liberator.NEW_BACKGROUND_TAB: return getBrowser().addTab(url, null, null, null); case liberator.NEW_WINDOW: window.open(); var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); whichwindow = wm.getMostRecentWindow("navigator:browser"); whichwindow.loadURI(url, null, null); return witchWindow.getBrowser().selectedTab; case "mark": default: liberator.echoerr("Exxx: Invalid 'where' directive in liberator.plugins.moreqmarks openurls(...)"); return false; } } //// MAPPINGS var modes = [liberator.modules.modes.NORMAL]; liberator.modules.mappings.addUserMap(modes, ["gj"], "Jump to QuickMark for current URL", function (arg) { var where = /\bquickmark\b/.test(liberator.modules.options["activate"]) ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; liberator.modules.quickmarks.jumpTo(arg, where, true); }, {arg: true}); liberator.modules.mappings.addUserMap(modes, ["gd"], "Delete QuickMark for current URL", function () { liberator.plugins.moreqmarks.remove('', liberator.modules.buffer.URL); }); liberator.modules.mappings.addUserMap(modes, ["gs"], "Push QuickMarkStack for current URL", function () { liberator.plugins.moreqmarks.add("", liberator.modules.buffer.URL, "stack"); }); liberator.modules.mappings.addUserMap(modes, ["gS"], "Pop QuickMarkStack and Jump", function () { var where = /\bquickmark\b/.test(liberator.modules.options["activate"]) ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; if(liberator.modules.quickmarks.jumpTo("", where, true, "stack")) { liberator.modules.quickmarks.remove("", "", "stack"); } }); liberator.modules.mappings.addUserMap(modes, ["gq"], "Queue QuickMarkQueue for current URL", function () { liberator.plugins.moreqmarks.add("", liberator.modules.buffer.URL, "queue"); }); liberator.modules.mappings.addUserMap(modes, ["gQ"], "Dequeue QuickMarkStack and Jump", function () { var where = /\bquickmark\b/.test(liberator.modules.options["activate"]) ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; if(liberator.modules.quickmarks.jumpTo("", where, true, "queue")) { liberator.modules.quickmarks.remove("", "", "queue"); } }); //// COMMANDS liberator.modules.commands.add(["qmarkpu[sh]", "qmpu[sh]"], "Push QuickMarkStack for current URL", function () { liberator.plugins.moreqmarks.add("", liberator.modules.buffer.URL, "stack"); }); liberator.modules.commands.add(["qmarkpo[p]", "qmpo[p]"], "Pop QuickMarkStack and Jump", function () { var where = /\bquickmark\b/.test(liberator.modules.options["activate"]) ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; liberator.modules.quickmarks.jumpTo("", where, true, "stack"); }); liberator.modules.commands.add(["stackli[st]", "stls"], "List QuickMarkStack", function () { liberator.plugins.moreqmarks.list("", "stack"); }); liberator.modules.commands.add(["qmarkqu[eue]", "qmqu[eue]"], "Queue QuickMarkQueue for current URL", function () { liberator.plugins.moreqmarks.add("", liberator.modules.buffer.URL, "queue"); }); liberator.modules.commands.add(["qmarkde[que]", "qmde[que]"], "Dequeue QuickMarkStack and Jump", function () { var where = /\bquickmark\b/.test(liberator.modules.options["activate"]) ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; liberator.modules.quickmarks.jumpTo("", where, true, "queue"); }); liberator.modules.commands.add(["queueli[st]", "quli[st]"], "List QuickMarkQueue", function () { liberator.plugins.moreqmarks.list("", "queue"); }); //// PUBLIC SECTION liberator.plugins.moreqmarks = { add: function (qmark, url, target) { if(use_position) { var win = window.content; var x, y; if (win.document.body.localName.toLowerCase() == "frameset") { x = 0; y = 0; } else { x = win.scrollMaxX ? win.pageXOffset / win.scrollMaxX : 0; y = win.scrollMaxY ? win.pageYOffset / win.scrollMaxY :
/*
 * ==VimperatorPlugin==
 * @name            youtubeamp.js
 * @description     this script gives you keyboard oprations for YouTube.com.
 * @description-ja  YouTube のプレーヤーをキーボードで操作できるようにする。
 * @author          janus_wel <janus_wel@fb3.so-net.ne.jp>
 * @version         0.12
 * @minversion      2.0pre 2008/10/16
 * ==/VimperatorPlugin==
 *
 * LICENSE
 *   New BSD License
 *
 * USAGE
 *   :ytinfo
 *     プレーヤーに関しての情報を表示する。今のところバージョンだけ。
 *   :ytpause
 *     再生 / 一時停止を切り替える。
 *   :ytmute
 *     音声あり / なしを切り替える。
 *   :ytsize
 *     最大化 / ノーマルを切り替える。動いてない。
 *   :ytseek [position]
 *     指定した場所にシークする。秒数で指定が可能。
 *     指定なしの場合一番最初にシークする。
 *   :ytseek! delta
 *     現在の位置から delta 分離れた所にシークする。秒数で指定が可能。
 *     マイナスを指定すると戻る。指定なしの場合変化しない。
 *   :ytvolume [volume]
 *     ボリュームを設定する。 0 ~ 100 が指定できる。
 *     指定なしの場合 100 にセットする。
 *   :ytvolume! delta
 *     ボリュームを現在の値から変更する。 -100 ~ +100 を指定可能。
 *     指定なしの場合変化しない。
 *
 * SEE ALSO
 *   http://code.google.com/apis/youtube/js_api_reference.html
 *
 * HISTORY
 *   2008/10/07 ver. 0.10   - initial written.
 * */

(function() {

Function.prototype.bind = function(object) {
    var __method = this;
    return function() {
        return __method.apply(object, arguments);
    };
};

// class definition
// YouTubePlayerController Class
function YouTubePlayerController() {
    this.initialize.apply(this, arguments);
}
YouTubePlayerController.prototype = {
    initialize: function() {
        this.fuller = this._changeToFull.bind(this);
    },

    constants: {
        VERSION: '0.12',

        CARDINAL_NUMBER: 10,

        YOUTUBE_DOMAIN: '.youtube.jp',
        YOUTUBE_URL:    '^http://[^.]+\\.youtube\\.com/',
        WATCH_URL:      'http://[^.]+\\.youtube\\.com/watch',
        WATCH_PAGE:     1,

        PLAYER_NODE_ID: 'movie_player',

        STATE_PLAYING: 1,

        SIZE_WIDTH_DEFAULT:  480,
        SIZE_HEIGHT_DEFAULT: 385,

        NAME_PLAYER_VERSION: 'PLAYER_VERSION',

        SEEKTO_DEFAULT:   0,
        SEEKBY_DEFAULT:   0,
        VOLUMETO_DEFAULT: 100,
        VOLUMEBY_DEFAULT: 0,

        HIDE_NODES: [
            'old-masthead',
            'watch-vid-title',
            'watch-other-vids',
            'old-footer',
            'copyright',
            'watch-main-area',
            'watch-comments-stats',
            'watch-video-response',
            'chrome-promo',
            'watch-video-quality-setting',
        ],
    },

    getControllerVersion: function() { return this.constants.VERSION; },

    pagecheck: function() {
        if(this.getURL().match(this.constants.WATCH_URL)) return this.constants.WATCH_PAGE;
        throw new Error('current tab is not watch page on youtube.com');
    },

    getURL: function() { return liberator.modules.buffer.URL; },

    _player: function() {
        if(this.pagecheck() === this.constants.WATCH_PAGE) {
            let player = this._getElementById(this.constants.PLAYER_NODE_ID);
            if(! player) throw new Error('player is not found');

            return player;
        }
        return null;
    },

    togglePlay: function() {
        var p = this._player();
        (p.getPlayerState() !== this.constants.STATE_PLAYING)
            ? p.playVideo()
            : p.pauseVideo();
    },

    toggleMute: function() {
        var p = this._player();
        p.isMuted() ? p.unMute() : p.mute();
    },

    toggleSize: function() {
        var p = this._player();
        (p.width == this.constants.SIZE_WIDTH_DEFAULT && p.height == this.constants.SIZE_HEIGHT_DEFAULT)
            ? this._fullSize()
            : this._normalSize();
    },

    _changeToFull: function() {
        var p = this._player();
        setTimeout(function() {
            p.width = content.innerWidth;
            p.height = content.innerHeight;
        }, 0);
    },

    _getElementById: function(id) {
        var e = window.content.document.getElementById(id);
        if(!e) return null;

        return e.wrappedJSObject
            ? e.wrappedJSObject
            : e;
    },

    _fullSize: function() {
        var b = this._getElementById('baseDiv');
        this.defMargin = b.style.margin;
        this.defPadding = b.style.padding;
        this.defWidth = b.style.width;
        b.style.margin = 0;
        b.style.padding = 0;
        b.style.width = '100%';

        for(let i=0, max=this.constants.HIDE_NODES.length ; i<max ; ++i) {
            let h = this._getElementById(this.constants.HIDE_NODES[i]);
            if(h) { h.style.display = 'none'; }
        }

        this._changeToFull();

        window.addEventListener(
            'resize',
            this.fuller,
            false
        );
    },

    _normalSize: function() {
        var b = this._getElementById('baseDiv');
        b.style.margin  = this.defMargin;
        b.style.padding = this.defPadding;
        b.style.width   = this.defWidth;

        for(let i=0, max=this.constants.HIDE_NODES.length ; i<max ; ++i) {
            let h = this._getElementById(this.constants.HIDE_NODES[i]);
            if(h) { h.style.display = 'block'; }
        }

        var p = this._player();
        p.width = this.constants.SIZE_WIDTH_DEFAULT;
        p.height = this.constants.SIZE_HEIGHT_DEFAULT;

        window.removeEventListener(
            'resize',
            this.fuller,
            false
        );
    },

    seekTo: function(position) {
        if(position) {
            if(position.match(/^(\d+):(\d+)$/)) {
                position = parseInt(RegExp.$1, this.constants.CARDINAL_NUMBER) * 60
                    + parseInt(RegExp.$2, this.constants.CARDINAL_NUMBER);
            }
            if(isNaN(position)) throw new Error('assign unsigned number : seekTo()');
        }
        else position = this.constants.SEEKTO_DEFAULT;

        var p = this._player();
        p.seekTo(position);
    },

    seekBy: function(delta) {
        if(delta) {
            if(isNaN(delta)) throw new Error('assign signed number : seekBy()');
        }
        else delta = this.constants.SEEKBY_DEFAULT;

        var p = this._player();
        var position = p.getCurrentTime();
        position += parseInt(delta, this.constants.CARDINAL_NUMBER);

        p.seekTo(position);
    },

    volumeTo: function(volume) {
        if(volume) {
            if(isNaN(volume)) throw new Error('assign unsigned number : volumeTo()');
        }
        else volume = this.constants.VOLUMETO_DEFAULT;

        var p = this._player();
        p.setVolume(volume);
    },

    volumeBy: function(delta) {
        if(delta) {
            if(isNaN(delta)) throw new Error('assign signed number : volumeBy()');
        }
        else delta = this.constants.VOLUMEBY_DEFAULT;

        var p = this._player();
        var volume = p.getVolume();
        volume += parseInt(delta, this.constants.CARDINAL_NUMBER);

        p.setVolume(volume);
    },
};

// global object
var controller = new YouTubePlayerController();

// command register
liberator.modules.commands.addUserCommand(
    ['ytinfo'],
    'display player information',
    function() {
        try {
            let info = [
                'controller version : ' + controller.getControllerVersion(),
            ].join('\n');
            liberator.echo(info, liberator.modules.commandline.FORCE_MULTILINE);
        }
        catch(e) { liberator.echoerr(e); }
    },
    {}
);

liberator.modules.commands.addUserCommand(
    ['ytpause'],
    'toggle play / pause',
    function() {
        try      { controller.togglePlay(); }
        catch(e) { liberator.echoerr(e); }
    },
    {}
);

liberator.modules.commands.addUserCommand(
    ['ytmute'],
    'toggle mute',
    function() {
        try      { controller.toggleMute(); }
        catch(e) { liberator.echoerr(e); }
    },
    {}
);

liberator.modules.commands.addUserCommand(
    ['ytseek'],
    'controll seek bar',
    function(args) {
        try {
            let arg = (args.length > 1)
                ? args[0].toString()
                : args.string;
            args.bang ? controller.seekBy(arg) : controller.seekTo(arg);
        }
        catch(e) { liberator.echoerr(e); }
    },
    {
        bang: true,
    }
);

liberator.modules.commands.addUserCommand(
    ['ytvolume'],
    'controll volume',
    function(args) {
        try {
            let arg = (args.length > 1)
                ? args[0].toString()
                : args.string;
            args.bang ? controller.volumeBy(arg) : controller.volumeTo(arg);
        }
        catch(e) { liberator.echoerr(e); }
    },
    {
        bang: true,
    }
);

liberator.modules.commands.addUserCommand(
    ['ytsize'],
    'toggle video size',
    function() {
        try      { controller.toggleSize(); }
        catch(e) { liberator.echoerr(e); }
    },
    {}
);

})()

// vim: set sw=4 ts=4 et;