nadesiko3
Version:
Japanese Programming Language
304 lines (303 loc) • 13.4 kB
JavaScript
import PartBrowserColor from './plugin_browser_color.mjs';
import PartBrowserSystem from './plugin_browser_system.mjs';
import PartBrowserDialog from './plugin_browser_dialog.mjs';
import PartBrowserLocation from './plugin_browser_location.mjs';
import PartBrowserAjax from './plugin_browser_ajax.mjs';
import PartBrowserDomBasic from './plugin_browser_dom_basic.mjs';
import PartBrowserDomEvent from './plugin_browser_dom_event.mjs';
import PartBrowserDomParts from './plugin_browser_dom_parts.mjs';
import PartBrowserHtml from './plugin_browser_html.mjs';
import PartBrowserStorage from './plugin_browser_storage.mjs';
import PartBrowserCanvas from './plugin_browser_canvas.mjs';
import PartBrowserGeolocation from './plugin_browser_geolocation.mjs';
import PartBrowserSpeech from './plugin_browser_speech.mjs';
import PartBrowserWebsocket from './plugin_browser_websocket.mjs';
import PartBrowserAudio from './plugin_browser_audio.mjs';
import PartBrowserHotkey from './plugin_browser_hotkey.mjs';
import PartBrowserChart from './plugin_browser_chart.mjs';
import PartBrowserCrypto from './plugin_browser_crypto.mjs';
const BrowserParts = [
PartBrowserColor,
PartBrowserSystem,
PartBrowserDialog,
PartBrowserLocation,
PartBrowserAjax,
PartBrowserDomBasic,
PartBrowserDomEvent,
PartBrowserDomParts,
PartBrowserHtml,
PartBrowserStorage,
PartBrowserCanvas,
PartBrowserGeolocation,
PartBrowserSpeech,
PartBrowserWebsocket,
PartBrowserAudio,
PartBrowserHotkey,
PartBrowserChart,
PartBrowserCrypto
];
const PluginBrowser = {
'meta': {
type: 'const',
value: {
pluginName: 'plugin_browser', // プラグインの名前
description: 'ブラウザ用のプラグイン', // 説明
pluginVersion: '3.6.0', // プラグインのバージョン
nakoRuntime: ['wnako'], // 対象ランタイム
nakoVersion: '3.6.0' // 要求なでしこバージョン
}
},
'初期化': {
type: 'func',
josi: [],
pure: true,
fn: function (sys) {
/* eslint no-global-assign: 0 */
const doc = (typeof document === 'undefined') ? { 'body': {}, 'querySelector': () => null } : document;
const win = (typeof window === 'undefined') ? { 'location': { 'href': 'http://localhost/' } } : window;
const nav = (typeof navigator === 'undefined') ? {} : navigator;
const loc = (typeof win.location === 'undefined') ? { 'href': 'http://localhost/' } : win.location;
// 定数を初期化
sys.__setSysVar('AJAX:ONERROR', (err) => { console.log(err); });
// オブジェクトを初期化
sys.__setSysVar('DOCUMENT', doc);
sys.__setSysVar('WINDOW', win);
sys.__setSysVar('NAVIGATOR', nav);
sys.__setSysVar('DOM親要素', doc.body);
sys.__setSysVar('ブラウザURL', loc.href);
// 便利なメソッドを定義
sys.__tohtml = (text) => {
return ('' + text)
.replace(/&/g, '&')
.replace(/>/g, '>')
.replace(/</g, '<');
};
sys.__tohtmlQ = (text) => {
return sys.__tohtml(text)
.replace(/"/g, '"')
.replace(/'/g, ''');
};
// 「!クリア」でDOMイベントを削除するため
sys.__dom_events = []; // [{}, {}, {} ...]
// DOM追加イベント
sys.__addEvent = (dom, event, func, setHandler) => {
// dom element
let domElement = null;
if (typeof (dom) === 'string') {
domElement = doc.querySelector(dom);
if (!domElement) {
throw new Error('DOMイベントが追加できません。要素が見当たりません。');
}
}
else {
domElement = dom;
}
// func
if (typeof (func) === 'string') {
func = sys.__findVar(func, null);
if (!func) {
throw new Error('DOMイベントが追加できません。関数が見当たりません。');
}
}
// make wrapper func
const wrapperFunc = (e) => {
sys.__setSysVar('対象', e.target);
sys.__setSysVar('対象イベント', e);
// 追加データが得られる場合
if (setHandler) {
setHandler(e, sys);
}
if (typeof func == 'function') {
return func(e, sys);
}
return false;
};
// add
sys.__dom_events.push({ dom: domElement, event, func: wrapperFunc, rawFunc: func });
const domWithEventListenr = domElement;
if (typeof domWithEventListenr.addEventListener === 'function') {
domWithEventListenr.addEventListener(event, wrapperFunc);
}
};
// キーイベントハンドラ
sys.__keyHandler = (e, sys) => {
sys.__setSysVar('押キー', e.key);
};
// マウスイベントハンドラ
sys.__mouseHandler = (e, sys) => {
const target = e.target;
if (target && target instanceof HTMLElement) {
const box = target.getBoundingClientRect();
sys.__setSysVar('マウスX', e.clientX - box.left);
sys.__setSysVar('マウスY', e.clientY - box.top);
if (e.buttons !== undefined) {
// (ref) https://developer.mozilla.org/ja/docs/Web/API/MouseEvent/buttons
const buttonLabels = ['', '左', '右', '', '中央'];
sys.__setSysVar('押ボタン', buttonLabels[e.buttons]);
}
}
};
// タッチイベントハンドラ
sys.__touchHandler = (e, sys) => {
const target = e.target;
if (target && target instanceof HTMLElement) {
const box = target.getBoundingClientRect();
const touches = e.changedTouches;
if (touches.length <= 0) {
return;
}
const ts = [];
for (let i = 0; i < touches.length; i++) {
const t = touches[i];
const tx = t.clientX - box.left;
const ty = t.clientY - box.top;
if (i === 0) {
sys.__setSysVar('タッチX', tx);
sys.__setSysVar('タッチY', ty);
}
ts.push([tx, ty]);
}
sys.__setSysVar('タッチ配列', ts);
return ts;
}
};
// DOMイベント削除 (探して削除)
sys.__removeEvent = (dom, event, func) => {
// dom
let domElement = null;
if (typeof (dom) === 'string') {
domElement = doc.querySelector(dom);
if (!domElement) {
throw new Error('DOMイベントが削除できません。要素が見当たりません。');
}
}
else {
domElement = dom;
}
// func
if (typeof (func) === 'string') {
func = sys.__findVar(func, null);
if (!func) {
throw new Error('DOMイベントが削除できません。関数が見当たりません。');
}
}
// find
for (let i = 0; i < sys.__dom_events.length; i++) {
const e = sys.__dom_events[i];
if (e.dom === dom && e.event === event && e.rawFunc === func) {
e.dom.removeEventListener(e.event, e.func);
sys.__dom_events.splice(i, 1);
break;
}
}
};
// requestAnimationFrame のためのid
sys.__requestAnimationFrameLastId = 0;
// DOMイベント全クリア
sys.__removeAllDomEvents = () => {
sys.__dom_events.forEach(e => {
e.dom.removeEventListener(e.event, e.func);
});
sys.__dom_events = [];
// requestAnimationFrame
if (sys.__requestAnimationFrameLastId > 0) {
win.cancelAnimationFrame(sys.__requestAnimationFrameLastId);
sys.__requestAnimationFrameLastId = 0;
}
};
// DOMに動的プロパティの取得と設定を追加する
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sys.__addPropMethod = (obj) => {
if (!obj) {
return;
}
if (obj.__setProp === undefined) {
obj.__setProp = (prop, value, sys) => {
sys.__exec('DOM設定変更', [obj, prop, value, sys]);
};
obj.__getProp = (prop, sys) => {
return sys.__exec('DOM設定取得', [obj, prop, sys]);
};
}
};
// Elementのクラスに対してDOMに動的プロパティの取得と設定を適用するよう登録する #1863
if (sys.__registPropAccessor && globalThis.Element) {
sys.__registPropAccessor(Element, function (prop, sys) {
// @ts-expect-error: use this
return sys.__exec('DOM設定取得', [this, prop, sys]);
}, function (prop, value, sys) {
// @ts-expect-error: use this
sys.__exec('DOM設定変更', [this, prop, value, sys]);
});
}
// DOM取得のために使う
sys.__query = (dom, commandName, isGetFunc) => {
// get element
let elm = null;
if (typeof dom === 'string') { // string to HTMLElement
elm = document.querySelector(dom);
if (!elm) {
elm = document.getElementById(dom);
}
}
else {
elm = dom;
}
// check element
if (!elm) {
if (isGetFunc) {
// 取得イベントではコンソールにヒントを出す
console.warn(`[ヒント](${sys.__getSysVar('__line')})『${commandName}』でDOM取得に失敗しています。DOM=`, dom);
}
else {
// 設定イベントでは実行時エラーにする
const desc = (typeof dom === 'string') ? dom : String(dom);
throw new Error(`『${commandName}』でクエリ『${desc}』でDOM取得に失敗しました。`);
}
}
sys.__addPropMethod(elm);
return elm;
};
// 動的にJSライブラリを取り込む
sys.__loadScript = (url) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.onload = () => { resolve(); };
script.onerror = () => {
reject(new Error(`Failed to load script at url: ${url}`));
};
document.getElementsByTagName('head')[0].appendChild(script);
});
};
}
},
'!クリア': {
type: 'func',
josi: [],
pure: true,
fn: function (sys) {
// chart.jsを破棄
if (sys.__chartjs) {
const chartjs = sys.__chartjs;
if (typeof chartjs.destroy === 'function') {
chartjs.destroy();
}
}
// 全DOMイベントをクリア
sys.__removeAllDomEvents();
}
}
};
BrowserParts.forEach((a) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const b = {};
Object.assign(b, a);
// 各モジュールでの初期化処理は認めない
if (typeof b['初期化'] !== 'undefined') {
delete b['初期化'];
}
Object.assign(PluginBrowser, b);
});
export default PluginBrowser;