CircleCI Workflow Panner

Pan across large workflow charts using your mouse instead of relying on the scrollbars. Set naturalScroll to false to disable inverted panning.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name        CircleCI Workflow Panner
// @namespace   antontsvil
// @match       *://app.circleci.com/*
// @grant       GM.getValue
// @grant       GM.setValue
// @require     https://unpkg.com/[email protected]/src/arrive.js
// @version     1.1
// @license     MIT
// @author      [email protected]
// @description Pan across large workflow charts using your mouse instead of relying on the scrollbars. Set naturalScroll to false to disable inverted panning.
// ==/UserScript==
/*jshint esversion: 8 */

const graphSelector = "[data-cy='workflow-graph']";
const graph = () => document.querySelector(graphSelector);
const html = () => document.querySelector('html');

let isDragging = false;
const dragStart = () => {
	isDragging = true;
	const gel = graph();
	gel.style.cursor = 'move';
	gel.style.userSelect = 'none';
};
const dragStop = () => {
	isDragging = false;
	const gel = graph();
	gel.style.cursor = 'default';
	gel.style.userSelect = 'initial';
};

const b = document.querySelector('body');
b.arrive(graphSelector, async () => {
	let naturalScroll = await GM.getValue('naturalScroll');
	if (naturalScroll!== false && naturalScroll !== true) {
		await GM.setValue('naturalScroll', true);
    naturalScroll = true;
	}
	const gel = graph();
	gel.addEventListener('mousedown', ({ target, button }) => {
		if (target.tagName === 'svg' && button === 0) {
			dragStart();
		}
	});
	gel.addEventListener('mouseup', (event) => {
		dragStop();
	});
	gel.addEventListener('mouseout', (event) => {
		if (event.relatedTarget === gel) {
			dragStop();
		}
	});
	gel.addEventListener('mousemove', (event) => {
		const el = graph();
		const rightSide = el.scrollWidth - el.clientWidth;
		const horizontalScroll = {
			left: naturalScroll
				? el.scrollLeft - event.movementX
				: el.scrollLeft + event.movementX,
		};
		const verticalScroll = {
			top: naturalScroll
				? html().scrollTop - event.movementY
				: html().scrollTop + event.movementY,
		};
		if (isDragging) {
			el.scrollTo(horizontalScroll);
			html().scrollTo(verticalScroll);
		}
	});
});