danoniplus 40.0.1 → 40.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/danoni_main.js +102 -61
- package/js/lib/danoni_constants.js +25 -15
- package/package.json +1 -1
package/js/danoni_main.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Source by tickle
|
|
6
6
|
* Created : 2018/10/08
|
|
7
|
-
* Revised : 2025/03/
|
|
7
|
+
* Revised : 2025/03/07
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 40.0
|
|
12
|
-
const g_revisedDate = `2025/03/
|
|
11
|
+
const g_version = `Ver 40.2.0`;
|
|
12
|
+
const g_revisedDate = `2025/03/07`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -37,13 +37,41 @@ const current = () => {
|
|
|
37
37
|
const targetScript = scripts.find(file => file.src.endsWith(`danoni_main.js`));
|
|
38
38
|
return targetScript.src;
|
|
39
39
|
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 現在URLのクエリパラメータから指定した値を取得
|
|
43
|
+
* @param {string} _name
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
const getQueryParamVal = _name => {
|
|
47
|
+
const param = new URL(location.href).searchParams.get(_name);
|
|
48
|
+
return param !== null ? decodeURIComponent(param.replace(/\+/g, ` `)) : null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// 常時デバッグを許可するドメイン
|
|
52
|
+
const g_reservedDomains = [
|
|
53
|
+
`danonicw.skr.jp`,
|
|
54
|
+
`tickle.cloudfree.jp`,
|
|
55
|
+
];
|
|
56
|
+
Object.freeze(g_reservedDomains);
|
|
57
|
+
|
|
58
|
+
// 外部参照を許可するドメイン
|
|
59
|
+
const g_referenceDomains = [
|
|
60
|
+
`cwtickle.github.io/danoniplus`,
|
|
61
|
+
`support-v\\d+--danoniplus.netlify.app`,
|
|
62
|
+
];
|
|
63
|
+
Object.freeze(g_referenceDomains);
|
|
64
|
+
|
|
40
65
|
const g_rootPath = current().match(/(^.*\/)/)[0];
|
|
41
66
|
const g_workPath = new URL(location.href).href.match(/(^.*\/)/)[0];
|
|
42
|
-
const g_remoteFlg = g_rootPath.match(`^https
|
|
43
|
-
|
|
67
|
+
const g_remoteFlg = g_referenceDomains.some(domain => g_rootPath.match(`^https://${domain}/`) !== null);
|
|
68
|
+
|
|
44
69
|
const g_randTime = Date.now();
|
|
45
70
|
const g_isFile = location.href.match(/^file/);
|
|
46
71
|
const g_isLocal = location.href.match(/^file/) || location.href.indexOf(`localhost`) !== -1;
|
|
72
|
+
const g_isDebug = g_isLocal ||
|
|
73
|
+
g_reservedDomains.some(domain => location.href.match(`^https://${domain}/`) !== null) ||
|
|
74
|
+
getQueryParamVal(`debug`) === `true`;
|
|
47
75
|
const isLocalMusicFile = _scoreId => g_isFile && !listMatching(getMusicUrl(_scoreId), [`.js`, `.txt`], { suffix: `$` });
|
|
48
76
|
|
|
49
77
|
window.onload = async () => {
|
|
@@ -468,44 +496,53 @@ const viewKeyStorage = (_name, _key = ``) => {
|
|
|
468
496
|
* オブジェクトのネスト表示処理
|
|
469
497
|
* @param {Object} _obj
|
|
470
498
|
* @param {Number} _indent
|
|
471
|
-
* @param {
|
|
472
|
-
* @param {
|
|
473
|
-
* @param {string} [key='']
|
|
499
|
+
* @param {boolean} [colorFmt=true] フォーマット加工フラグ
|
|
500
|
+
* @param {string} [rootKey=''] オブジェクトの最上位プロパティ名
|
|
474
501
|
* @param {Object} [_parent=null]
|
|
475
502
|
* @returns {string}
|
|
476
503
|
*/
|
|
477
|
-
const formatObject = (_obj, _indent = 0, {
|
|
504
|
+
const formatObject = (_obj, _indent = 0, { colorFmt = true, rootKey = `` } = {}) => {
|
|
478
505
|
if (_obj === null || typeof _obj !== 'object') {
|
|
479
506
|
return JSON.stringify(_obj);
|
|
480
507
|
}
|
|
481
|
-
if (seen.has(_obj)) {
|
|
482
|
-
return '[Circular]';
|
|
483
|
-
}
|
|
484
|
-
seen.add(_obj);
|
|
485
508
|
const baseIndent = getIndent(_indent);
|
|
486
509
|
const nestedIndent = getIndent(_indent + 1);
|
|
487
510
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
511
|
+
/**
|
|
512
|
+
* データの装飾処理
|
|
513
|
+
* @param {string|boolean|number|Object} _value
|
|
514
|
+
* @param {string} _rootKey
|
|
515
|
+
* @returns {string}
|
|
516
|
+
*/
|
|
517
|
+
const formatValue = (_value, _rootKey) => {
|
|
491
518
|
if (colorFmt) {
|
|
492
|
-
if (typeof _value ===
|
|
493
|
-
|
|
519
|
+
if (typeof _value === C_TYP_STRING) {
|
|
520
|
+
|
|
521
|
+
// カラーコードの色付け処理
|
|
522
|
+
_value = escapeHtml(_value).replaceAll(`\n`, `<br>`);
|
|
523
|
+
const colorCodePattern = /(#|0x)(?:[A-Fa-f0-9]{6}(?:[A-Fa-f0-9]{2})?|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{3})/g;
|
|
494
524
|
if (colorCodePattern.test(_value)) {
|
|
495
525
|
return _value.replace(colorCodePattern, (match) =>
|
|
496
526
|
`<span style="color:${match.replace(`0x`, `#`)}">◆</span>${match.replace(`0x`, `#`)}`);
|
|
497
527
|
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
528
|
+
} else if (typeof _value === C_TYP_BOOLEAN) {
|
|
529
|
+
|
|
530
|
+
// boolean値の色付け処理
|
|
531
|
+
return (_value ? `<span style="color:#66ff66">✔ true</span>` :
|
|
532
|
+
`<span style="color:#ff9999">❌ false</span>`);
|
|
533
|
+
|
|
534
|
+
} else if (typeof _value === C_TYP_NUMBER) {
|
|
535
|
+
|
|
536
|
+
if (_rootKey.startsWith(`scrollDir`)) {
|
|
537
|
+
// scrollDirXのスクロール方向表示処理
|
|
538
|
+
return _value === 1 ? `1|<span style="color:#ff9999">↑</span>` : `-1|<span style="color:#66ff66">↓</span>`;
|
|
539
|
+
|
|
540
|
+
} else if (_rootKey.startsWith(`keyCtrl`) && !_rootKey.startsWith(`keyCtrlPtn`)) {
|
|
541
|
+
// keyCtrlXの対応キー表示処理
|
|
542
|
+
return (g_kCd[_value] && _value !== 0) ? `${_value}|<span style="color:#ffff66">${g_kCd[_value]}</span>` : `----`;
|
|
504
543
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
if (typeof _value === 'object' && _value !== null) {
|
|
508
|
-
return formatObject(_value, _indent + 1, { seen, colorFmt, key }, _parent);
|
|
544
|
+
} else if (typeof _value === C_TYP_OBJECT && _value !== null) {
|
|
545
|
+
return formatObject(_value, _indent + 1, { colorFmt, rootKey: _rootKey });
|
|
509
546
|
}
|
|
510
547
|
}
|
|
511
548
|
return JSON.stringify(_value);
|
|
@@ -519,7 +556,7 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
519
556
|
if (colorFmt && _obj.length > 100) {
|
|
520
557
|
const filteredArray = _obj.reduce((result, value, index) => {
|
|
521
558
|
if (hasVal(value)) {
|
|
522
|
-
result.push(`${index}: ${formatValue(value,
|
|
559
|
+
result.push(`${index}: ${formatValue(value, rootKey)}`);
|
|
523
560
|
}
|
|
524
561
|
return result;
|
|
525
562
|
}, []);
|
|
@@ -530,11 +567,11 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
530
567
|
.map(value => {
|
|
531
568
|
const isNestedObject = typeof value === 'object' && value !== null;
|
|
532
569
|
return isArrayOfArrays
|
|
533
|
-
? `${nestedIndent}${formatValue(value,
|
|
570
|
+
? `${nestedIndent}${formatValue(value, rootKey)}`
|
|
534
571
|
: isNestedObject
|
|
535
|
-
? formatObject(value, _indent + 1, {
|
|
536
|
-
: formatValue(value,
|
|
537
|
-
}).join(isArrayOfArrays ? `,<br>` : `, `);
|
|
572
|
+
? formatObject(value, _indent + 1, { colorFmt, rootKey })
|
|
573
|
+
: formatValue(value, rootKey)
|
|
574
|
+
}).filter(val => !hasVal(val) || val !== `----`).join(isArrayOfArrays ? `,<br>` : `, `);
|
|
538
575
|
|
|
539
576
|
return `[${isArrayOfArrays ? `<br>` : ``}${formattedArray}${isArrayOfArrays ? `<br>${baseIndent}` : ''}]`;
|
|
540
577
|
}
|
|
@@ -543,12 +580,12 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
543
580
|
const formattedEntries = Object.entries(_obj)
|
|
544
581
|
.map(([key, value]) => {
|
|
545
582
|
const isNestedObject = typeof value === 'object' && value !== null;
|
|
546
|
-
const
|
|
583
|
+
const baseKey = rootKey === `` ? key : rootKey;
|
|
547
584
|
const formattedValue = isNestedObject
|
|
548
|
-
? formatObject(value, _indent + 1, {
|
|
549
|
-
: formatValue(value,
|
|
585
|
+
? formatObject(value, _indent + 1, { colorFmt, rootKey: baseKey }, _obj)
|
|
586
|
+
: formatValue(value, baseKey);
|
|
550
587
|
return `<br>${nestedIndent}"${key}": ${formattedValue}`;
|
|
551
|
-
}).join(`,`);
|
|
588
|
+
}).filter(val => !hasVal(val) || val !== `----`).join(`,`);
|
|
552
589
|
|
|
553
590
|
let result = `{${formattedEntries}<br>${baseIndent}}`;
|
|
554
591
|
if (!colorFmt) {
|
|
@@ -825,14 +862,17 @@ const createScText = (_obj, _settingLabel, { displayName = `option`, dfLabel = `
|
|
|
825
862
|
* 各画面の汎用ショートカットキー表示
|
|
826
863
|
* @param {string} _displayName
|
|
827
864
|
*/
|
|
828
|
-
const createScTextCommon = _displayName =>
|
|
829
|
-
|
|
830
|
-
.
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
865
|
+
const createScTextCommon = _displayName => {
|
|
866
|
+
if (g_btnPatterns[_displayName]) {
|
|
867
|
+
Object.keys(g_btnPatterns[_displayName]).filter(target => document.getElementById(`btn${target}`) !== null)
|
|
868
|
+
.forEach(target =>
|
|
869
|
+
createScText(document.getElementById(`btn${target}`), target, {
|
|
870
|
+
displayName: _displayName, targetLabel: `btn${target}`,
|
|
871
|
+
dfLabel: g_lblNameObj[`sc_${_displayName}${target}`] ?? ``,
|
|
872
|
+
x: g_btnPatterns[_displayName][target],
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
};
|
|
836
876
|
|
|
837
877
|
/**
|
|
838
878
|
* ショートカットキー有効化
|
|
@@ -849,7 +889,9 @@ const setShortcutEvent = (_displayName, _func = () => true, { displayFlg = true,
|
|
|
849
889
|
document.onkeydown = evt => commonKeyDown(evt, _displayName, _func, dfEvtFlg);
|
|
850
890
|
document.onkeyup = evt => commonKeyUp(evt);
|
|
851
891
|
};
|
|
852
|
-
if (
|
|
892
|
+
if (!g_btnWaitFrame[_displayName] ||
|
|
893
|
+
g_btnWaitFrame[_displayName].s_frame === 0 ||
|
|
894
|
+
(g_initialFlg && g_btnWaitFrame[_displayName].initial)) {
|
|
853
895
|
evList();
|
|
854
896
|
} else {
|
|
855
897
|
setTimeout(() => {
|
|
@@ -1588,7 +1630,9 @@ const createCss2Button = (_id, _text, _func = () => true, {
|
|
|
1588
1630
|
|
|
1589
1631
|
// ボタン有効化操作
|
|
1590
1632
|
if (initDisabledFlg) {
|
|
1591
|
-
if (
|
|
1633
|
+
if (!g_btnWaitFrame[groupName] ||
|
|
1634
|
+
g_btnWaitFrame[groupName].b_frame === 0 ||
|
|
1635
|
+
(g_initialFlg && g_btnWaitFrame[groupName].initial)) {
|
|
1592
1636
|
} else {
|
|
1593
1637
|
style.pointerEvents = C_DIS_NONE;
|
|
1594
1638
|
setTimeout(() => style.pointerEvents = rest.pointerEvents ?? C_DIS_AUTO,
|
|
@@ -2263,16 +2307,6 @@ const copyTextToClipboard = async (_textVal, _msg) => {
|
|
|
2263
2307
|
}
|
|
2264
2308
|
};
|
|
2265
2309
|
|
|
2266
|
-
/**
|
|
2267
|
-
* 現在URLのクエリパラメータから指定した値を取得
|
|
2268
|
-
* @param {string} _name
|
|
2269
|
-
* @returns {string}
|
|
2270
|
-
*/
|
|
2271
|
-
const getQueryParamVal = _name => {
|
|
2272
|
-
const param = new URL(location.href).searchParams.get(_name);
|
|
2273
|
-
return param !== null ? decodeURIComponent(param.replace(/\+/g, ` `)) : null;
|
|
2274
|
-
};
|
|
2275
|
-
|
|
2276
2310
|
/**
|
|
2277
2311
|
* ローディング文字用ラベルの作成
|
|
2278
2312
|
* @returns {HTMLDivElement}
|
|
@@ -5005,7 +5039,7 @@ const dataMgtInit = () => {
|
|
|
5005
5039
|
multiAppend(divRoot,
|
|
5006
5040
|
createCss2Button(`btnBack`, g_lblNameObj.b_back, () => true,
|
|
5007
5041
|
Object.assign(g_lblPosObj.btnResetBack, {
|
|
5008
|
-
resetFunc: () =>
|
|
5042
|
+
resetFunc: () => [`title`, `precondition`].includes(prevPage) ? titleInit() : g_moveSettingWindow(false),
|
|
5009
5043
|
}), g_cssObj.button_Back),
|
|
5010
5044
|
|
|
5011
5045
|
createCss2Button(`btnPrecond`, g_lblNameObj.b_precond, () => true,
|
|
@@ -5160,6 +5194,12 @@ const preconditionInit = () => {
|
|
|
5160
5194
|
g_customJsObj.precondition.forEach(func => func());
|
|
5161
5195
|
|
|
5162
5196
|
multiAppend(divRoot,
|
|
5197
|
+
|
|
5198
|
+
// データ管理画面へ移動
|
|
5199
|
+
createCss2Button(`btnReset`, g_lblNameObj.dataReset, () => {
|
|
5200
|
+
dataMgtInit();
|
|
5201
|
+
}, g_lblPosObj.btnReset, g_cssObj.button_Reset),
|
|
5202
|
+
|
|
5163
5203
|
createCss2Button(`btnBack`, g_lblNameObj.b_back, () => true,
|
|
5164
5204
|
Object.assign(g_lblPosObj.btnPrecond, {
|
|
5165
5205
|
resetFunc: () => {
|
|
@@ -6853,7 +6893,8 @@ const getKeyCtrl = (_localStorage, _extraKeyName = ``) => {
|
|
|
6853
6893
|
const isUpdate = prevPtn !== -1 && g_keyObj.prevKey !== g_keyObj.currentKey;
|
|
6854
6894
|
g_keyCopyLists.multiple.filter(header => g_keyObj[`${header}${basePtn}`] !== undefined && isUpdate)
|
|
6855
6895
|
.forEach(header => g_keyObj[`${header}${copyPtn}`] = structuredClone(g_keyObj[`${header}${basePtn}`]));
|
|
6856
|
-
g_keyCopyLists.simple.
|
|
6896
|
+
g_keyCopyLists.simple.filter(header => g_keyObj[`${header}${basePtn}`] !== undefined && isUpdate)
|
|
6897
|
+
.forEach(header => g_keyObj[`${header}${copyPtn}`] = g_keyObj[`${header}${basePtn}`]);
|
|
6857
6898
|
|
|
6858
6899
|
g_keycons.groups.forEach(type => {
|
|
6859
6900
|
let maxPtn = 0;
|
|
@@ -10791,8 +10832,8 @@ const mainInit = () => {
|
|
|
10791
10832
|
[`lblCredit`, `lblDifName`].forEach(labelName => changeStyle(labelName, g_lblPosObj.musicInfoOFF));
|
|
10792
10833
|
}
|
|
10793
10834
|
|
|
10794
|
-
//
|
|
10795
|
-
if (!
|
|
10835
|
+
// デバッグ時のみフレーム数を残す
|
|
10836
|
+
if (!g_isDebug) {
|
|
10796
10837
|
lblframe.style.display = C_DIS_NONE;
|
|
10797
10838
|
}
|
|
10798
10839
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Source by tickle
|
|
7
7
|
* Created : 2019/11/19
|
|
8
|
-
* Revised : 2025/03/
|
|
8
|
+
* Revised : 2025/03/02 (v40.1.0)
|
|
9
9
|
*
|
|
10
10
|
* https://github.com/cwtickle/danoniplus
|
|
11
11
|
*/
|
|
@@ -248,7 +248,7 @@ const updateWindowSiz = () => {
|
|
|
248
248
|
},
|
|
249
249
|
btnPrecond: {
|
|
250
250
|
x: g_btnX(1 / 4), y: g_sHeight - 20, w: g_btnWidth(1 / 4), h: 16, siz: 12,
|
|
251
|
-
visibility:
|
|
251
|
+
visibility: g_isDebug ? `visible` : `hidden`,
|
|
252
252
|
},
|
|
253
253
|
btnSafeMode: {
|
|
254
254
|
x: g_btnX(), siz: 18,
|
|
@@ -2326,22 +2326,32 @@ const g_shortcutObj = {
|
|
|
2326
2326
|
// b_frame: ボタンの有効化フレーム数、s_frame: ショートカットキーの有効化フレーム数
|
|
2327
2327
|
// initial: 初回のみ有効化時間を設定する場合、trueを設定
|
|
2328
2328
|
const g_btnWaitFrame = {
|
|
2329
|
-
initial: {
|
|
2330
|
-
title: {
|
|
2331
|
-
dataMgt: {
|
|
2332
|
-
precondition: {
|
|
2333
|
-
option: {
|
|
2334
|
-
difSelector: {
|
|
2335
|
-
settingsDisplay: {
|
|
2336
|
-
exSetting: {
|
|
2337
|
-
keyConfig: {
|
|
2338
|
-
loading: {
|
|
2339
|
-
loadingIos: {
|
|
2340
|
-
main: {
|
|
2341
|
-
result: {
|
|
2329
|
+
initial: {},
|
|
2330
|
+
title: {},
|
|
2331
|
+
dataMgt: {},
|
|
2332
|
+
precondition: {},
|
|
2333
|
+
option: { initial: true },
|
|
2334
|
+
difSelector: {},
|
|
2335
|
+
settingsDisplay: {},
|
|
2336
|
+
exSetting: {},
|
|
2337
|
+
keyConfig: { s_frame: 30 },
|
|
2338
|
+
loading: {},
|
|
2339
|
+
loadingIos: {},
|
|
2340
|
+
main: {},
|
|
2341
|
+
result: { s_frame: 120 },
|
|
2342
2342
|
};
|
|
2343
|
+
Object.keys(g_btnWaitFrame).forEach(key => {
|
|
2344
|
+
if (!g_btnWaitFrame[key].b_frame) {
|
|
2345
|
+
g_btnWaitFrame[key].b_frame = 0;
|
|
2346
|
+
}
|
|
2347
|
+
if (!g_btnWaitFrame[key].s_frame) {
|
|
2348
|
+
g_btnWaitFrame[key].s_frame = 0;
|
|
2349
|
+
}
|
|
2350
|
+
});
|
|
2343
2351
|
|
|
2344
2352
|
// 主要ボタンのリスト
|
|
2353
|
+
// - btn + プロパティ名に合致するボタンid名に対して、
|
|
2354
|
+
// どの位置(X方向)にショートカット名を表示するかを設定
|
|
2345
2355
|
const g_btnPatterns = {
|
|
2346
2356
|
title: { Start: 0, Comment: -10 },
|
|
2347
2357
|
dataMgt: { Back: 0, Environment: -35, Highscores: -35, CustomKey: -35, Others: -35 },
|