Greasy Fork

mutations

GitHub mutations observer library script

目前为 2017-04-21 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/28721/189706/mutations.js

/* GitHub mutations observer library script v0.2.0
 * Detect changes to various elements and trigger an event
 * This script is meant to be used as a library for GitHub-based userscripts
 * Copyright © 2017 Rob Garrison
 * License: MIT
 */
/* jshint esnext:true, unused:true */
(() => {
	"use strict";

	// prefix for event & document body class name, e.g. "ghmo:container"
	const prefix = "ghmo",
		disableAttr = `data-${prefix}-disable`,
		debounceInterval = 200,
		targets = {
			// pjax container (covers general, repo & gists)
			"[data-pjax-container]": {
				count: 0,
				name: "container"
			},
			// comment preview active
			".js-preview-body": {
				count: 0,
				name: "preview"
			},
			// progressively loaded comments; "# items not shown"
			// example: https://github.com/isaacs/github/issues/18
			".js-discussion": {
				count: 0,
				name: "comments"
			},
			// progressively loaded content (diff files)
			".js-diff-progressive-container, .data.blob-wrapper, .js-diff-load-container": {
				count: 0,
				name: "diff"
			}
		},
		list = Object.keys(targets);

	function fireEvents() {
		list.forEach(selector => {
			if (targets[selector].count > 0) {
				// event => "ghmo:container", "ghmo:comments"
				const event = new Event(prefix + ":" + targets[selector].name);
				document.dispatchEvent(event);
			}
			targets[selector].count = 0;
		});
	}

	// prevent error when library is loaded at document-start & no body exists
	document.addEventListener("DOMContentLoaded", () => {
		const container = document.querySelector("body");
		let timer;
		// prevent script from installing more than once
		if (container && !container.classList.contains(prefix + "-enabled")) {
			container.classList.add(prefix + "-enabled");

			// bound to document.body... this may be bad for performance
			// http://stackoverflow.com/a/39332340/145346
			new MutationObserver(mutations => {
				clearTimeout(timer);
				/* document.body attribute used to disable updates; it *should not*
				 * be used regularly as multiple scripts may enable or disable the
				 * observers at inappropriate times. It is best that each script handles
				 * the mutation events triggered by this library on its own
				 */
				if (container.getAttribute(disableAttr)) {
					return;
				}
				let mindx, target, lindx,
					llen = list.length,
					mlen = mutations.length;
				// avoiding use of forEach loops for performance reasons
				for (mindx = 0; mindx < mlen; mindx++) {
					target = mutations[mindx].target;
					if (target) {
						for (lindx = 0; lindx < llen; lindx++) {
							if (target.matches(list[lindx])) {
								targets[list[lindx]].count++;
							}
						}
					}
					timer = setTimeout(() => {
						fireEvents();
					}, debounceInterval);
				}
			}).observe(container, {
				childList: true,
				subtree: true
			});

		}
	});

})();