Chrome 拡張機能　メモ帳アプリ

# manifest.json
    {
      "name": "POPUP Utlilty",
      "description": "Utilty",
      "version": "1.0",
      "manifest_version": 3,
      "permissions": [
        "tabs", "storage"
      ],
      "action": {
        "default_title": "POPUP Utlilty",
        "default_popup": "popup.html"
                 }
    }    
マニフェスト V3での記載
　
# popup.html
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <link rel="stylesheet" href="popup.css">
            <script src="jquery-3.6.0.min.js"></script>
            <script src="time.js"></script>
        </head>
       <body>
        <div class="tabs">
            <input id="all" type="radio" name="tab_item" checked>
            <label class="tab_item" for="all">Utility</label>
            <input id="programming" type="radio" name="tab_item">
            <label class="tab_item" for="programming">タブ２</label>
            <input id="memotext" type="radio" name="tab_item">
            <label class="tab_item" for="memotext">★Memo★</label>
            <!--ここからタブ１ -->
            <div class="tab_content" id="all_content">
              <div class="tab_content_description">
                <div class="date_today_time">
                  <h3>Today Date：</h3>
                  <p id="id_date_today"></p>
                </div>
               <h2>HOGE</h2>
              </div>
            </div>
            <!--ここからタブ２-->
            <div class="tab_content" id="programming_content">
              <div class="tab_content_description">
                <h2>リンク集</h2>
              </div>
            </div>
            <!--ここからタブ３-->
            <div class="tab_content" id="memotext_content">
              <div class="tab_content_description">
                <h2>Memo：</h2>
                <p>※plaintext 、UTF-8 、短期保存でローカルストレージに記憶、忘却で削除<br>ダウンロードは、テキストファイル </p>
                <div id="MemoTextArea">
                <textarea id="id_memo"></textarea><br>
                <input type="button" id="id_save" value="短期保存">
                <p>【↓テキストファイルを取り込み表示/テキストファイルをダウンロード☟】<br>※文字コード【UTF-8】に限る</p>
                <input type="file" id="id_openfile">
                <input type="button" id="id_savefile" value="メモをダウンロード">
                <input type="button" id="id_clear" value="メモを忘却">
              </div>
              </div>
            </div>
          </div>
          <script src="memoScript.js"></script>
        </body>
    </html>

# popup.css
    body {
        font-family: "meiryo","メイリオ","arial",sans-serif;
        font-size: 14px;
      }
    /*--------------------ここからタブのスタイル------------*/
    /*タブ切り替え全体のスタイル*/
    .tabs {
        margin-top: 50px;
        padding-bottom: 40px;
        background-color: #fff;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
        width: 600px;
        margin: 0 auto;}

      /*タブのスタイル*/
      .tab_item {
        width: calc(100%/3);
        height: 50px;
        border-bottom: 3px solid #5ab4bd;
        background-color: #d9d9d9;    
        line-height: 50px;
        font-size: 16px;
        text-align: right;
        color: #565656;
        display: block;
        float: left;
        text-align: center;
        font-weight: bold;
        transition: all 0.2s ease;
      }
      .tab_item:hover {
        opacity: 0.75;
        cursor:pointer;
      }

      /*ラジオボタンを全て消す*/
      input[name="tab_item"] {
        display: none;
      }

      /*タブ切り替えの中身のスタイル*/
      .tab_content {
        display: none;
        padding: 40px 40px 0;
        clear: both;
        overflow: hidden;
      }

      /*選択されているタブのコンテンツのみを表示*/
      #all:checked ~ #all_content,
      #programming:checked ~ #programming_content,
      #memotext:checked ~ #memotext_content {
        display: block;
      }

      /*選択されているタブのスタイルを変える*/
      .tabs input:checked + .tab_item {
        background-color: #57ac9d;
        color: #fff;
      }
    /*--------------------ここまでがタブスタイル----------------*/
      #id_memo {
        border: 1px solid #57c9bf;
        width: 525px;
        height: 250px;
        font-size: 16px;
        background-color: #fffce6;
      }

# memoScript.js
    window.onload = () => {
        let memo = localStorage['Memo'];
        if (memo == null) {
            memo = '';
        }
        document.getElementById('id_memo').value = memo;
    }
    document.getElementById('id_save').onclick = () => {
        localStorage['Memo'] = document.getElementById('id_memo').value;
    }
    document.getElementById('id_openfile').onchange = function() {
        let file = this.files[0];
        if (file == null) return;
        let reader = new FileReader;
        reader.onload = function() {
            document.getElementById('id_memo').value = reader.result;
        }
        reader.readAsText(file);
    }
    document.getElementById('id_savefile').onclick = () => {
        let memo =document.getElementById('id_memo').value;
        let objectURL = window.URL.createObjectURL(new Blob([memo]));
        let a = document.createElement('a');
        a.download = 'memo.txt';
        a.href = objectURL;
        a.click();
    }
    document.getElementById('id_clear').onclick = () => {
        let textareForm = document.getElementById('id_memo');
        textareForm.value = '';
        localStorage['Memo'] = textareForm.value;
    }

# time.js
    $(function(){
        setInterval(function(){
        var now = new Date();
        var y = now.getFullYear();
        var m = now.getMonth() + 1;
        var d = now.getDate();
        var w = now.getDay();
        var wd = ['日', '月', '火', '水', '木', '金', '土'];
        var h = ('0' + now.getHours()).slice(-2);
        var mi = ('0' + now.getMinutes()).slice(-2);
        var s = ('0' + now.getSeconds()).slice(-2);
        $('#id_date_today').text(y + '/' + m + '/' + d + '/' + h + ':' + mi + ' ' + '(' + wd[w] + ')');
        }, 5000);
        });