您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
作者在 Jira v8.13.15 编写和应用,其它版本可能需要调整源码。另外,需要调整域名匹配规则。
- // ==UserScript==
- // @name Hi, Jira 🚀
- // @namespace https://xianghongai.github.io/
- // @version 1.2.2
- // @description 作者在 Jira v8.13.15 编写和应用,其它版本可能需要调整源码。另外,需要调整域名匹配规则。
- // @author Nicholas Hsiang
- // @icon https://www.feature.com/favicon.ico
- // @match *://jira.feature-inc.cn/*
- // @grant unsafeWindow
- // @license MIT
- // ==/UserScript==
- (function () {
- 'use strict';
- /**
- * 🚀 可编辑字段禁止点击文本编辑,只能通过点击编辑按钮图标操作
- */
- function editableField(event) {
- const targetEle = event.target;
- // i. 点击的是“编辑”按钮图标
- const isEdit = hasClass(targetEle, 'aui-iconfont-edit');
- // ii. 点击的是图片、链接
- // img
- // a
- const inWhitelist = ['img', 'a'].includes(targetEle.tagName.toLowerCase());
- if (inWhitelist || isEdit) {
- return true;
- }
- // 1. 父层为可编辑字段 (非 Description)
- const editableFieldParent = getParents(
- targetEle,
- '.editable-field:not(#description-val)'
- );
- const isEditableFieldParent =
- editableFieldParent && hasClass(editableFieldParent, 'inactive');
- // 2. 当前层为可编辑字段 (非 Description)
- const isEditableField =
- hasClass(targetEle, 'editable-field') && hasClass(targetEle, 'inactive');
- // 3. Description 字段
- const isDescriptionField = getParents(targetEle, '.user-content-block');
- if (isEditableFieldParent || isEditableField || isDescriptionField) {
- event.preventDefault();
- event.stopPropagation();
- return false;
- }
- }
- /**
- * 🚀 快捷功能
- */
- function keyboardShortcut(event) {
- // 在 macOS 上,Option (ALT) 键有特殊功能,它用于输入特殊字符和符号。
- // 按下 Option+T 时,macOS 可能将其解释为一个特殊字符输入,而不是单纯的修饰键+字母组合,
- // 这就导致 JavaScript 事件系统接收到的不是标准的按键事件,而是 "Unidentified"。
- // event.code 表示物理按键的位置,与键盘布局无关。
- // 按 ALT+L 添加 Link
- if (
- event.altKey &&
- ((event.key === 'Unidentified' && event.code === 'KeyL') ||
- event.key.toLowerCase() === 'l')
- ) {
- document.querySelector('#link-issue')?.click();
- }
- }
- /**
- * 🚀 DOM 事件
- */
- function click(event) {
- editableField(event);
- }
- document.addEventListener('click', click, true);
- function keydown(event) {
- keyboardShortcut(event);
- }
- document.addEventListener('keydown', keydown, true);
- // #region COMMON
- function hasClass(el, className) {
- if (el.classList) {
- return el.classList.contains(className);
- }
- return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
- }
- function getParents(elem, selector) {
- for (; elem && elem !== document; elem = elem.parentNode) {
- if (elem.matches(selector)) return elem;
- }
- return null;
- }
- // #endregion
- })();