slideshareのスライドをスクロールでめくるユーザースクリプト

wheel de slideというユーザースクリプトとして作り直した。以下の内容はもう古い。

version 1.2: speakerdeck, docs.google.comにも対応。

version 1.3: slideshareでめくり終えたときに表示されるスクリーンを考慮するように修正。

https://gist.github.com/raw/3765455/f74808d68d8211b06139d10c6c82c65d9660f3bc/slideshare_scroll.user.js

// ==UserScript==
// @id slideshare_scroll
// @name slideshare scroll
// @version 1.3
// @namespace http://rikuba.com/
// @include http://slideshare.net/*
// @include http://www.slideshare.net/*
// @include http://speakerdeck.com/*
// @include https://speakerdeck.com/*
// @include https://docs.google.com/presentation/embed*
// @run-at document-end
// ==/UserScript==

var siteinfos = [
    {
        url: /^https?:\/\/speakerdeck\.com\//,
        container: '#presenter, #player',
        prev: 'a.prev',
        next: 'a.next'
    },
    {
        url: /^http:\/\/(?:www\.)?slideshare\.net\/mobile\//,
        container: '.slideShow',
        prev: '#previous_slide',
        next: '#next_slide'
    },
    {
        url: /^https?:\/\/(?:www\.)?slideshare\.net\//,
        container: '#svPlayerId, #player',
        prev: ['.lastScreenContainer .close-btn', '.btnPrevious'],
        next: '.btnNext'
    },
    {
        url: /^https:\/\/docs\.google\.com\/presentation\/embed\?/,
        container: 'body',
        prev: 'a[role="button"][title="前へ"]',
        next: 'a[role="button"][title="次へ"]'
    }
];

function findMatchingSiteinfo(url) {
    for (var i = 0, l = siteinfos.length; i < l; ++i) {
        if (siteinfos[i].url.test(url)) {
            return siteinfos[i];
        }
    }
    return null;
}


var MATCHES_SELECTOR = (function () {
    var elem = document.documentElement, i, name;
    for (i = 0; name = arguments[i++];) if (elem[name]) return name;
})('matchesSelector', 'mozMatchesSelector', 'webkitMatchesSelector', 'oMatchesSelector');

function handleEvent(e) {
    var types = ['wheel', 'mousewheel'];
    e.currentTarget.removeEventListener(types[+!types.indexOf(e.type)], this);
    this.handleEvent = onwheel;
    this.handleEvent(e);
}

function onwheel(e) {
    if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) {
        return;
    }

    FIND_CONTAINER: {
        for (var elem = e.target; elem; elem = elem.parentNode) {
            // event target may be text node in Google Chrome
            if (elem.nodeType === 1 &&
                elem[MATCHES_SELECTOR](this.siteinfo.container)) {
                break FIND_CONTAINER;
            }
        }
        return;
    }

    if (e.deltaY > 0 || e.wheelDelta < 0) {
        e.preventDefault();
        clickElement(e.currentTarget, this.siteinfo.next);
    } else if (e.deltaY < 0 || e.wheelDelta > 0) {
        e.preventDefault();
        clickElement(e.currentTarget, this.siteinfo.prev);
    }
}


function clickElement(element, selectors) {
    if (Array.isArray(selectors)) {
        return selectors.some(_clickElement, element);
    }
    return _clickElement.call(element, selectors);
}

function _clickElement(selector) {
    var target = this.querySelector(selector);
    if (target) {
        target.click();
        return true;
    }
    return false;
}


(function main() {
    var siteinfo = findMatchingSiteinfo(location.href), listener;
    if (siteinfo) {
        listener = { siteinfo: siteinfo, handleEvent: handleEvent };
        document.addEventListener('wheel', listener);
        document.addEventListener('mousewheel', listener);
    }
}());

HTMLElement::click()、ユーザースクリプトを作るのに便利。