0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自分用にCustom8 JSMacro KeyPadを作りました

Last updated at Posted at 2024-08-30

自分用にCustom8 JSMacro KeyPadというお気楽ツールを作りました

ボタン毎にのJSが登録できてマクロボタン的に実行する画面です。
evalで実行してるだけです。

ElgadoのStream DECKが格好良いので真似したくてしょぼい画面を作りました。

image.png

1.ツールの画面

Stream DECKと全然違いますが…オマージュということで、JSのマクロ登録するとこんな感じです。

Screenshot 2024-08-30 09.41.36.png

2.ソースコード

ソースコードというかcodepenに作ったのでそちらでソースもご確認ください。
https://codepen.io/sf-os/pen/YzoOKed

See the Pen Custom8 JSMacro KeyPad by sf-os (@sf-os) on CodePen.

※少しCSS追加したバージョンもあります。 https://codepen.io/sf-os/pen/VwJVeBj

3.登録できるマクロの例

ボタン番号選んでボタン名とJSを登録するだけです。localStoregeに保存されます。

image.png

  • Hello World
alert("hello world");
  • 台風情報HPを開く
var result = window.confirm('気象庁台風情報を開きますか');
if (result) {window.open('https://www.jma.go.jp/bosai/map.html#6/33.978/140.682/&elem=root&typhoon=all&contents=typhoon')};
  • Yahoo NewsのRSS取得
// div要素の作成
const yahooNewsDiv = document.createElement('div');
yahooNewsDiv.id = 'yahoonews';
document.body.appendChild(yahooNewsDiv);

// RSSフィードのURL
const rssUrls = [
  'https://news.yahoo.co.jp/rss/topics/top-picks.xml',
  'https://news.yahoo.co.jp/rss/topics/domestic.xml',
  'https://news.yahoo.co.jp/rss/topics/world.xml'
];

// RSSフィードを取得して表示する関数
async function fetchAndDisplayRss(url) {
  try {
    const response = await fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(url)}`);
    const data = await response.json();
    const parser = new DOMParser();
    const xmlDoc = parser.parseFromString(data.contents, 'text/xml');
    
    const channel = xmlDoc.querySelector('channel');
    const title = channel.querySelector('title').textContent;
    const items = channel.querySelectorAll('item');
    
    let html = `<h2>${title}</h2><ul>`;
    
    items.forEach((item, index) => {
      if (index < 5) {
        const itemTitle = item.querySelector('title').textContent;
        const itemLink = item.querySelector('link').textContent;
        const itemPubDate = new Date(item.querySelector('pubDate').textContent);
        html += `
          <li>
            <a href="${itemLink}" target="_blank">${itemTitle}</a>
            <br>
            <small>公開日時: ${itemPubDate.toLocaleString('ja-JP')}</small>
          </li>
        `;
      }
    });
    
    html += '</ul>';
    yahooNewsDiv.innerHTML += html;
  } catch (error) {
    console.error('エラーが発生しました:', error);
    yahooNewsDiv.innerHTML += `<p>RSSフィードの取得に失敗しました: ${url}</p>`;
  }
}

// 全てのRSSフィードを取得して表示
async function fetchAllRssFeeds() {
  for (const url of rssUrls) {
    await fetchAndDisplayRss(url);
    // 各リクエスト間に3秒の遅延を追加
    await new Promise(resolve => setTimeout(resolve, 3000));
  }
}

// スクリプトの実行
fetchAllRssFeeds();
  • シンプルメモ
function createMemoModal() {
  // 既存のモーダルがあれば削除
  const existingModal = document.getElementById('memoModal');
  if (existingModal) {
    existingModal.remove();
  }

  // モーダルの作成
  const modal = document.createElement('dialog');
  modal.id = 'memoModal';
  modal.style.backgroundColor = '#888';
  modal.style.padding = '20px';
  modal.style.borderRadius = '5px';

  // タイトルの作成
  const title = document.createElement('h2');
  title.textContent = 'シンプル・メモ';
  title.style.marginTop = '0';
  title.style.marginBottom = '15px';
  title.style.color = 'white';

  // テキストエリアの作成
  const textarea = document.createElement('textarea');
  textarea.id = 'memoText';
  textarea.rows = 10;
  textarea.cols = 50;
  textarea.style.width = '100%';
  textarea.style.marginBottom = '15px';

  // 保存&終了ボタンの作成
  const saveButton = document.createElement('button');
  saveButton.textContent = '保存&終了';
  saveButton.style.padding = '5px 10px';
  saveButton.onclick = function() {
    const memoContent = textarea.value;
    localStorage.setItem('memosave20240831-1', memoContent);
    modal.close();
  };

  // モーダルに要素を追加
  modal.appendChild(title);
  modal.appendChild(textarea);
  modal.appendChild(saveButton);

  // bodyにモーダルを追加
  document.body.appendChild(modal);

  // ローカルストレージから値を取得して表示
  const savedMemo = localStorage.getItem('memosave20240831-1');
  if (savedMemo) {
    textarea.value = savedMemo;
  }

  // モーダルを表示
  modal.showModal();
};

createMemoModal();
  • 時計
// div要素を作成
const clockDiv = document.createElement('div');
clockDiv.id = 'clock';
document.body.appendChild(clockDiv);

// 時計を更新する関数
function updateClock() {
    const now = new Date();
    const days = ['', '', '', '', '', '', ''];
    
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const date = String(now.getDate()).padStart(2, '0');
    const day = days[now.getDay()];
    const hours = String(now.getHours()).padStart(2, '0');
    const minutes = String(now.getMinutes()).padStart(2, '0');
    const seconds = String(now.getSeconds()).padStart(2, '0');

    const timeString = `${year}${month}${date}日 (${day}) ${hours}:${minutes}:${seconds}`;
    
    document.getElementById('clock').textContent = timeString;
}

// 1秒ごとに時計を更新
setInterval(updateClock, 1000);

// 初回の更新を即時実行
updateClock();

  • 地図
let leafletPromise = null;

function loadLeaflet() {
  if (leafletPromise) {
    return leafletPromise;
  }

  leafletPromise = new Promise((resolve, reject) => {
    if (window.L) {
      resolve(window.L);
      return;
    }

    const linkElement = document.createElement('link');
    linkElement.rel = 'stylesheet';
    linkElement.href = 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
    document.head.appendChild(linkElement);

    const scriptElement = document.createElement('script');
    scriptElement.src = 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js';
    scriptElement.onload = () => resolve(window.L);
    scriptElement.onerror = () => reject(new Error('Leafletスクリプトの読み込みに失敗しました。'));
    document.body.appendChild(scriptElement);
  });

  return leafletPromise;
}

function createLeafletMap(containerId, lat, lon, zoom) {
  return loadLeaflet().then(L => {
    let container = document.getElementById(containerId);
    if (!container) {
      container = document.createElement('div');
      container.id = containerId;
      container.style.width = '100%';
      container.style.height = '400px';
      document.body.appendChild(container);
    }

    const map = L.map(container).setView([lat, lon], zoom);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    L.marker([lat, lon]).addTo(map)
      .bindPopup('ここが指定された位置です')
      .openPopup();

    return map;
  });
}

// 使用例
createLeafletMap('map-container-1', 35.6586, 139.7454, 15)
  .then(map => console.log('地図1が作成されました'));




4.おわりに

しょぼいけど、ランチャー的に使えそうなので記事にしました。
CSS得意なひとならもっとかっこよくできそうです。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?