何??
例えば/docs/index.htmlから/img/atlas.pngを読み込みたいとき
絶対パスで書くと
/docs/index.html
<img src="/img/atlas.png">
相対パスで書くと
/docs/index.html
<img src="../img/atlas.png">
これを他の場所でも使いまわせるようにjsファイルに移すと
/docs/index.html
...
<script src="../src/util.js"></script>
...
/src/util.js
const src='../img/atlas.png';
addEventListener('DOMContentloaded',()=>document.body.append(Object.assign(new Image(),{src})));
→読めないじゃん
これは単に/src/util.jsからの相対パスにしているからだが
/docs/index.htmlからの相対パスに書き換えたところで他のファイルから/src/util.jsを読み込んだときに読まない
どうする?
これ
<script>
のsrcから/docs/index.html→/src/util.jsまでの相対パスを読んで
予め/src/util.jsにある/src/util.js→/img/atlas.pngの相対パスに付け足す
/src/util.js
document.querySelector('script[src$="util.js"]').src
// → "https://example.com/src/util.js"
[x$=y]はyで終わる属性xに合致する属性セレクタ MDN
これでパスの部分が取れるねと思ったらなんと絶対パスが返ってきた
困ったので無理矢理outerHTMLと正規表現でぶんどる
/src/util.js
document.querySelector('script[src$="util.js"]').outerHTML.match(/\"(.*)util.js\"/)[1]
// → "../src/"
あとで結合しやすいようにutil.jsの部分は除いて検索している
そして
/src/util.js
const root=document.querySelector('script[src$="util.js"]').outerHTML.match(/\"(.*)util.js\"/)[1],
src=root+'../img/atlas.png';
addEventListener('DOMContentloaded',()=>document.body.append(Object.assign(new Image(),{src})));
これでどこからでも/img/atlas.pngが読めますね
めでたしめでたし……
追記: 2023/08/13
- 空文字列になると不都合な場面があった
- グローバルなオブジェクトに入れた方が使い勝手が良い
self.root=document.querySelector('script[src$="util.js"]').outerHTML.match(/\"(.*)util.js\"/)[1]||'./';