User JavaScript and CSS (Chrome Extension)를 사용하여 Redmine을 맞춤 설정해 보았습니다.

이 기사는 free_dev_com Advent Calendar 2019 - Adventar 7 일째 기사입니다.

User JavaScript and CSS란 무엇입니까?



Chrome 확장 프로그램으로 제공되는 기존 웹 사이트에 자체 Javascript 및 CSS를 포함하는 라이브러리입니다.
User JavaScript and CSS - Chrome 웹 스토어

이것을 이용해, 다크 모드가 없는 웹사이트에 다크 모드를 실장해 보거나, Yahoo!의 사이트에 자신이 좋아하는 캐릭터의 일러스트를 표시시키거나, 여러가지 할 수 있습니다.
이번에는 사내 작업 관리에 사용하는 Redmine에서 티켓 설명에 나오는 스 니펫 내용을 클립 보드에 복사하는 기능을 Javascript로 구현해 보았습니다.

화면 설계



스 니펫 테두리 밖, 오른쪽 하단에 복사 아이콘을 배치하고,



아이콘을 클릭하면 「복사했습니다!」의 다이얼로그를 표시하기로 합니다.



구현



아이콘 불러오기



이번에는 Font Awesome 아이콘을 사용합니다.
Font Awesome의 경우 여기

흐름은 다음과 같습니다.
  • Font Awesome을로드하는 링크 태그 만들기
  • head 태그를 취득해, 그 아이 요소로서 방금 작성한 link 태그를 추가한다

  • redmine.js
    const link = document.createElement('link');
    link.setAttribute('rel', 'stylesheet');
    link.setAttribute('href', 'https://use.fontawesome.com/releases/v5.6.3/css/all.css');
    
    document.getElementsByTagName('head')[0].appendChild(link);
    

    스니펫의 테두리 밖, 오른쪽 하단 부분에 요소를 배치



    흐름은 다음과 같습니다.

    스 니펫 (pre 태그) 가져 오기 -> 각 스 니펫을 배열로 가져옵니다.



    각 스 니펫에 대해 다음을 수행합니다.


  • 복사 버튼을 배치하기위한 p 태그 만들기 (snippet)
  • 나중에 복사 버튼이 될 span 태그 만들기 (copyButton)
  • (copyButton에 title, innerHTML, className 등의 속성을 설정한다)
  • copyButton에 클릭 이벤트 리스너 부여 (내용은 아래)
  • 복사 대상이되는 textarea 태그를 작성 (textarea 태그가 아니어도 갈 수 있습니다)
  • 스 니펫의 문장을 textarea 태그로 설정
  • 만든 textarea 태그를 body 태그의 자식 요소로 배치 -> 선택 -> 복사
  • textarea 태그는 더 이상 필요하지 않으므로 제거합니다
  • 복사가 완료되었다는 메시지 표시

  • copyButton을 snippet 바로 뒤에 배치합니다.

    redmine.js
    // スニペットのタグを選択
    const snippets = document.getElementsByTagName('pre');
    // console.log(snippets); // HTMLCollection
    // console.log(typeof snippets); // object
    
    // コピーボタンを配置
    Object.keys(snippets).forEach(function (index) {
        let snippet = snippets[index];
        let p = document.createElement('p');
        p.className = 'copy-snippet';
    
        let copyButton = document.createElement('span');
        copyButton.title = 'Copy to Clipboard';
        copyButton.innerHTML = '<i class="far fa-copy"></i> Copy';
        copyButton.className = 'copy-button';
    
        copyButton.addEventListener('click', function () {
            let copyTarget = document.createElement('textarea');
            copyTarget.textContent = snippet.innerText.trim(); // 見た目に合わせて文末改行削る?
            let body = document.getElementsByTagName('body')[0];
            body.appendChild(copyTarget);
            copyTarget.select();
            document.execCommand("copy");
            body.removeChild(copyTarget);
            // 後処理まで終わったらおまけ
            (function () {
                alert('コピーしました!');
            })();
        });
        p.appendChild(copyButton);
        snippet.parentNode.insertBefore(p, snippet.nextSibling);
    });
    

    기타



    화면 오른쪽 하단에 개구리의 일러스트를 넣고 전체를 CSS로 정돈합니다.

    redmine.js
    // カエルがペコペコおじぎする GIF
    const imageUrl = 'https://sozai-good.com/download?id=2451&type=7&subnumber=0&extention=gif';
    
    // 画像挿入処理
    let img = document.createElement('img');
    img.id = 'inserted-image';
    img.height = 105;
    img.src = imageUrl;
    const wrapper = document.getElementById('wrapper');
    wrapper.parentNode.insertBefore(img, wrapper.nextSibling);
    

    redmine.css
    #wrapper, #main {
        background-image: url("https://www.pakutaso.com/shared/img/thumb/mizuho1102dssd_TP_V.jpg");
        background-repeat: no-repeat;
        background-size: cover;
        background-attachment: fixed;
        opacity: 0.96;
    }
    
    #top-menu {
        /*background-color: darkgreen;*/
        background-color: rgba(10, 106, 10, 0.9);
    }
    
    #header, #footer {
        /*background-color: forestgreen;*/
        background-color: rgba(0, 0, 0, 0.5);
    }
    
    #main-menu li a {
        /*background-color: darkgreen;*/
        background-color: rgba(10, 106, 10, 0.6);
    }
    
    #main-menu li .selected {
        color: lightgreen;
    }
    
    #content {
        margin-bottom: 20px;
    }
    
    #sidebar {
        background-color: white;
    }
    
    #footer {
        position: fixed;
        background-color: black;
        right: 0;
        bottom: 0;
    }
    
    pre, .CodeRay {
        font-family: Monaco, monospace;
    }
    
    #inserted-image {
        position: fixed;
        right: 25px;
        bottom: 45px;
    }
    
    .copy-snippet {
        text-align: right;
    }
    
    .copy-button {
        cursor: pointer;
        background: none;
        border: 0;
    
        /* settings when hovered */
        /*transition: color 0.1s linear;*/
    }
    
    .copy-button:hover {
        color: red;
    }
    

    Redmine 공식 페이지 보기



    Defect #32525: CSV related tests fail with Rails 5.2.4 - Redmine



    했어!

    효용


  • "명령은 복사하여 붙여 넣기"가 암묵적인 규칙이 되고 있는 프로덕션 환경으로의 릴리스 작업에 있어서, 축일 스니펫의 내용을 마우스로 선택하는 수고를 생략할 수 있습니다.
  • 자신의 화면에만 구현되므로 다른 사람에게 자랑 할 수 있습니다.
  • 프론트 주위가 조금 즐거워집니다.
  • 좋은 웹페이지 즐겨찾기