コンパスに自動入力するscript
使用例
JSONファイルから入力するbookmarklet
ここをクリックして取得したコードの先頭にjavascript:をつけて、ブックマークのURLに貼り付ける bundle前
code:script.ts
import { upload } from "../scrapbox-file-uploader/mod.ts";
import { write, CompassSource } from "./mod.ts";
(async () => {
const file = await upload({ accept: ".json" });
if (!file) return;
const json = JSON.parse(await file.text()) as CompassSource;
write(json);
})();
入力するJSONの形式
2022-08-25 19:26:13 Dateをnumberに変えた
JSONに変換した時にデータが消えてしまうことをすっかり忘れていた
code:mod.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
/** コンパスの登山計画作成フォームに入力するデータ */
export interface CompassSource {
/** 山名 */
area: string;
/** 目的 */
purpose: 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22;
/** ルート */
route: {
/** 入山口 */
start: {
prefecture: PrefectureId;
name: string;
/** 入山日時 (UNIX時刻) */
date: number;
};
/** 経由地点 */
points: Point[];
/** 下山口 */
end: {
prefecture: PrefectureId;
name: string;
/** 入山日時 (UNIX時刻) */
date: number;
};
};
/** コンパスのグループ番号 */
party?: number;
/** 同行者情報 */
members: {
/** 男性の同行者人数 */
malesCount: number;
/** 女性の同行者人数 */
femalesCount: number;
/** 手動入力する同行者リスト */
members: {
name: string;
sex: "male" | "female";
email?: string;
}[];
};
/** 緊急連絡先リスト */
emergencies: {
name: string;
tel: string;
email?: string;
}[];
/** 加入している山岳保険の名前 */
insurance?: string;
/** jRO会員番号 未加入の場合はundefinedにする */
jro?: string;
/** ココヘリ会員番号 未加入の場合はundefinedにする */
cocoheli?: string;
/** 携行する食料の回数 */
foodCount: number;
/** 携行する行動食の回数 */
trailSnackCount: number;
/** 飲料水ありならtrue */
hasWater: boolean;
/** 個人装備 */
personalEquipment: string;
/** 共同装備 */
partyEquipment: string;
/** 無線機を持っているならtrue */
hasRadioEquipment: boolean;
/** エスケープルート */
escapeRoot: string;
/** 備考 */
note: string;
}
/** 経由地・泊地データ */
export interface Point {
/** 泊地ならtrue */
isSleep: boolean;
/** 地点名 */
name: string;
/** 到着時刻 */
arrived: Time;
/** 出発時刻 */
left: Time;
}
/** 時刻データ */
export interface Time {
hours: number;
minutes: number;
}
/** 都道府県に対応する番号リスト */
export type PrefectureId = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47;
実装
フォームに自動入力する
code:sh
code:mod.ts
declare const pointsblur: () => void;
declare const addpname0: () => void;
declare const addemlist0: () => void;
export const write = (source: CompassSource): void => {
if (
) return;
// 登山山域・目的
input("area").value = source.area;
select("purpose").value = ${source.purpose};
// ルート
// 入山口
{
select("inpref").value = ${source.route.start.prefecture};
input("inname").value = source.route.start.name;
const start = new Date(source.route.start.date * 1000);
select("starty").value = ${start.getFullYear()};
select("startm").value = ${start.getMonth() + 1};
select("startd").value = ${start.getDate()};
select("intimeh").value = ${start.getHours()};
select("intimem").value = ${start.getMinutes()};
}
// 地点
for (let i = 0; i < source.route.points.length; i++) {
if (source.route.points.length > document.getElementsByClassName("pointblock").length) {
pointsblur();
}
const point = source.route.pointsi; inputWithValue(points[${i}][type], point.isSleep ? 2 : 1).checked = true;
input(points[${i}][name]).value = point.name;
select(points[${i}][intimeh]).value = ${point.arrived.hours};
select(points[${i}][intimem]).value = ${point.arrived.minutes};
select(points[${i}][outtimeh]).value = ${point.left.hours};
select(points[${i}][outtimem]).value = ${point.left.minutes};
}
// 下山口
{
select("outpref").value = ${source.route.end.prefecture};
input("outname").value = source.route.end.name;
const end = new Date(source.route.end.date * 1000);
select("endy").value = ${end.getFullYear()};
select("endm").value = ${end.getMonth() + 1};
select("endd").value = ${end.getDate()};
select("outtimeh").value = ${end.getHours()};
select("outtimem").value = ${end.getMinutes()};
}
// 同行者など
if (source.party) select("party").value = ${source.party};
select("pnum1").value = ${source.members.malesCount};
select("pnum2").value = ${source.members.femalesCount};
for (let i = 0; i < source.members.members.length; i++) {
if (source.members.members.length > document.getElementsByClassName("pname").length) {
addpname0();
}
const member = source.members.membersi; if(member.email) input(pname[${i}][name]).value = member.email;
inputWithValue(pname[${i}][sex], member.sex === "male" ? 1 : 2).checked = true;
if (member.email) input(pname[${i}][email]).value = member.email;
}
// 緊急連絡先の登録
for (let i = 0; i < source.emergencies.length; i++) {
if (source.emergencies.length > document.getElementsByClassName("emlist").length) {
addemlist0();
}
const emergency = source.emergenciesi; input(emlist[${i}][name]).value = emergency.name;
input(emlist[${i}][tel]).value = emergency.tel;
if (emergency.email) input(emlist[${i}][email]).value = emergency.email;
}
// 保険
inputWithValue("insurance", source.insurance ? 1 : 0).checked = true;
if (source.insurance) input("insurance_name").value = source.insurance;
if (source.jro) {
input("isjro").checked = true;
input("jro_name").value = source.jro;
}
if (source.cocoheli) {
input("ishitokoko").checked = true;
input("hitokoko").value = source.cocoheli;
}
// 装備
select("food1").value = ${source.foodCount};
select("food2").value = ${source.trailSnackCount};
inputWithValue("water", source.hasWater ? 1 : 0).checked = true;
textarea("item1").value = source.personalEquipment;
textarea("item2").value = source.partyEquipment;
inputWithValue("radioequipment", source.hasRadioEquipment ? 1 : 0).checked = true;
textarea("escaperoot").value = source.escapeRoot;
textarea("note").value = source.note;
};
const input = (name: string): HTMLInputElement => {
const inputEl = document.querySelector(input[name="${name}"]);
if (!(inputEl instanceof HTMLInputElement)) throw Error(No input[name="${name}"] found.);
return inputEl;
};
const textarea = (name: string): HTMLTextAreaElement => {
const textareaEl = document.querySelector(textarea[name="${name}"]);
if (!(textareaEl instanceof HTMLTextAreaElement)) throw Error(No textarea[name="${name}"] found.);
return textareaEl;
};
const select = (name: string): HTMLSelectElement => {
const selectEl = document.querySelector(select[name="${name}"]);
if (!(selectEl instanceof HTMLSelectElement)) throw Error(No select[name="${name}"] found.);
return selectEl;
};
const inputWithValue = (name: string, value: number): HTMLInputElement => {
const inputEl = document.querySelector(input[name="${name}"][value="${value}"]);
if (!(inputEl instanceof HTMLInputElement)) throw Error(No input[name="${name}"][value="${value}"] found.);
return inputEl;
};