原三溪展@横浜美術館の出品リスト(の魚拓)を埋め込む。
<object type="application/pdf" width="600" height="800" data="PDF_URL"></object>
iOS 内蔵ブラウザ( Safari ベース)ではプレビューとしてしか表示されない。のでページがめくれないのが残念。
.oO(ところで。HTML5では(4にあったような)空タグを避ける <ほにゃらら /> 的な記法は無くなったのかねえ)
参考
原三溪展@横浜美術館の出品リスト(の魚拓)を埋め込む。
<object type="application/pdf" width="600" height="800" data="PDF_URL"></object>
iOS 内蔵ブラウザ( Safari ベース)ではプレビューとしてしか表示されない。のでページがめくれないのが残念。
.oO(ところで。HTML5では(4にあったような)空タグを避ける <ほにゃらら /> 的な記法は無くなったのかねえ)
参考
-hide_banner
オプションを追加すればおk。
$ ffmpeg -hide_banner ... $ ffprobe -hide_banner ...
-hide_banner
Suppress printing banner.
All FFmpeg tools will normally show a copyright notice, build options and library versions. This option can be used to suppress printing this information.
~/.bashrc
に書いておきましょう。私は ffprobe にだけ設定しました。
alias ffmpeg='ffmpeg -hide_banner' alias ffprobe='ffprobe -hide_banner'
のコメントを書いたときに Ruby のリファレンスマニュアルを見直していました。Ruby 的にはどうやら「属性参照」と呼ぶらしいです(仮称のようにも感じますが)。ちなみに英語マニュアルだと Assignment Methods (代入メソッド)でした1。
代入
例:
foo.bar = baz文法:
式`.'識別子 '=' 式(中略)
属性参照
式1 `.' 識別子 '=' 式2
式 1
を評価して得られるオブジェクトに対して、識別子=
というメソッドを、式 2
を引数にして呼び出します。例:
class C def foo @foo end def foo=( v ) @foo = v end end c = C.new c.foo = 5 # c.foo=( 5 ) のように変換される p c.foo # => 5属性は
Module#attr
を使って同じように定義できます。例:
class C attr :foo, true end c = C.new c.foo = 5 # c.foo=( 5 ) のように変換される p c.foo # => 5
ブログ本館では、3か月毎に以下のような展覧会リストを(自分のために)作っています。
このブログで次のようなことが出来るように JavaScript を書いてみました。
いままで書いていたはてなダイアリーでは JS が使えなかったので、やりたくても出来なかったのです。
JS を一から書いたのは初めてに近いので、下手くそなのは見逃してください。
const trs = document.querySelectorAll('table > tbody > tr'); const re = /^([\d\/]+)-([\d\/]+)/; const yyyy = "2020" // 該当する記事の年に変更する const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // 当日真夜中 for (let i=1; i < trs.length; i++) { // i=0 は項目名なので排除 let tr = trs[i] let titleElem = tr.childNodes[1]; let scheduleElem = tr.childNodes[3]; let text = scheduleElem.innerText; let dates = text.match(re); // dates[1]が期間開始日、dates[2]が期間終了日 // 終了日関係 let endDateArray = dates[2].split("/"); // 会期末未定の場合には日付を 00 にすることで以下の処理を無視する if (endDateArray[endDateArray.length - 1] === "00") { continue; } let endDate; if (endDateArray.length === 2) { endDate = new Date(yyyy + "/" + endDateArray.join("/")); } else { endDate = new Date(endDateArray.join("/")); } let endDateCountFromToday = (endDate - today)/86400/1000 // 展覧会終了日を過ぎていたら表示しない(visibility:collapse;) if (endDateCountFromToday < 0) { tr.setAttribute('style', 'display:none;'); continue; } else if (endDateCountFromToday < 7) { titleElem.setAttribute('style', 'color:#39f;'); // 終了日7日以内ならばタイトルtitleElemを青色に } // 開始日関係 let startDateArray = dates[1].split("/"); let startDate; if (startDateArray.length === 2) { startDate = new Date(yyyy + "/" + startDateArray.join("/")); } else { startDate = new Date(startDateArray.join("/")); } let startDateCountFromToday = (startDate - today)/86400/1000 // 展覧会開始日が96日前よりも前だったらopacityをかなり小さくする if (startDateCountFromToday > 96) { tr.setAttribute('style', 'opacity:0.25;'); continue; } // 展覧会開始日が28日前よりも前だったらopacityを小さくする if (startDateCountFromToday > 28) { tr.setAttribute('style', 'opacity:0.6;'); continue; } // 展覧会開始日を過ぎていたら日程部分scheduleElemをボールドに if (startDateCountFromToday <= 0) { scheduleElem.setAttribute('style', 'background:#eee;font-weight:bold;'); // 展覧会開始日を過ぎて7日以内ならばタイトルtitleElemを赤色に if (startDateCountFromToday > -7 && endDateCountFromToday >= 7) { titleElem.setAttribute('style', 'color:#f63;'); } continue; } // 展覧会開始前3日以内だったらタイトルtitleElemを茶色に if (startDateCountFromToday <= 3) { titleElem.setAttribute('style', 'color:#c42;'); } }
もちろんこの JavaScript を <script>
タグに挟んで記事末尾に入れておくわけです。
参考:HTMLのテーブルの要素を消したり薄くしたりするCSSは(Safari除く) - 別館 子子子子子子(ねこのここねこ)はてブロ部
備忘録なので、誰の参考にもならなくてもいいのです(イイワケ
DRY じゃない部分をそのうち関数にしてみたりしよう(ひとりごと
世間的には要素を非表示にするときに「display: none;
か visibility: hidden;
」を使うようですね(例:【CSS】非表示にするならどっち?display:noneとvisibility:hiddenの違い | BeGeek)。が、テーブルの行であれば visibility: collapse;
というのがかなり使えるようです。原理的にはコストがかからないようなので速いのではないでしょうか。
残念なことに Safari*1 では visibility: collapse;
が visibility: hidden;
と同じになってしまい、行の表示が詰められませんでしたorz
collapse
- <table> の行、列、列グループ、行グループでは、行や列が不可視になり、 (表の列や行に
display: none
が適用された場合のように) 占めていた領域も除去されます。しかし、他の行や列の寸法は、不可視になった行や列のセルが存在するときのように計算されます。この値は表全体の幅や高さを強制的に再計算することなく、すばやく行や列を不可視にすることができます。- その他の要素では、
collapse
はhidden
と同じと扱われます。visibility - CSS: カスケーディングスタイルシート | MDN(下線は引用者追加)
上にも書きましたが、いちおう再度書きます。行要素 <tr>
を非表示にするときにコストが低そうですが、他の要素では特に意味が無さそうです。
文字も背景色も普段より薄く表示してみたいなあ、と思ったときにいちいち文字と背景色の値を変更するのは面倒。ということでまとめて薄く表示させるのは opacity
プロパティを使います。
CSS の
opacity
プロパティは、要素の透明度、または要素の裏にあるコンテンツが見える度合いを設定します。
引数は0以上1以下です。つまり opacity: 1;
とか opacity: 0.6;
などのように書きます。
サンプルとして2018年度気になる展覧会その4(冬編) - 子子子子子子(ねこのここねこ)はてブロ部のテーブルを使います。なおブラウザは「Chrome バージョン: 71.0.3578.98(Official Build) (64 ビット)」です。
<tr>
を非表示にする場合「王羲之書法の残影―唐時代への道程―」の行を取り扱います。
display: none;
指定した行が詰められています。完全に消えてしまって、位置表示もされませんね。
visibility: hidden;
行が存在した場所が空白として空きます。
visibility: collapse;
display:none;
のように行が詰められていますが、存在した位置は表示されます。
<td>
を非表示にする場合
display: none;
指定した要素が消え、右にあった要素が左へ詰められています。完全に消えてしまって、位置表示もされませんね。
visibility: hidden;
指定した要素が表示されません。この例では下の枠線が消えてしまい、真下の要素が縦に伸びたように見えます。
visibility: collapse;
指定した要素が表示されません。visibility:hidden;
と同じ表示になっています。
<tr>
を薄く表示する例やはり「王羲之書法の残影―唐時代への道程―」の行を取り扱います。
opacity: 1;
オリジナルと同じです。
opacity: 0.5;
半分の濃度。わりと薄くなります。
opacity: 0.1;
かなり読みづらいです。
Markdownの脚注記法に対応しました
はてなブログの記事編集画面で利用できるMarkdownモードで、Makrndownの脚注記法に対応しました。
:
今回サポートした脚注は、PHP Markdown Extra由来の記法です。
Footnotes
Footnotes work mostly like reference-style links. A footnote is made of two things: a marker in the text that will become a superscript number; a footnote definition that will be placed in a list of footnotes at the end of the document.
いままでのはてなダイアリー由来の脚注*1と Markdown 方式の脚注1とは残念ながら全く別個なのよね。書く側が統一しなきゃいけないので、なんだかなあと思う。はてなダイアリーの脚注で表記しておけば、マウスポインタを当てたときに脚注の内容が表示されるので便利、でも Markdown 方式の脚注では表示されない。結局、はてなブログでは旧来のはてな記法で脚注しておくほうが良いと思う。
はてなブログで全てのリンクを別ウィンドウで開くならば <base target="_blank">
を設定しておけば済むのだけど、しかしこの状況でははてなブログ内のリンクまで別ウィンドウで開いてしまう。これはウザい。ってことで先人の知恵を借りた。けど若干のチューニングをしたのでメモっておく。
はてなブログの「設定>デザイン>カスタマイズ>ヘッダ」の「タイトル下」に HTML を書く欄があるので、そこに
<script>window.addEventListener("DOMContentLoaded",()=>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>anchor.setAttribute('target','_blank');));</script>
をコピペして「変更を保存する」ボタンを押して保存。これでおk。
<script> window.addEventListener("DOMContentLoaded", () => { document.querySelectorAll("a[href^='http']:not([href*='" + location.hostname + "'])").forEach( (anchor) => { anchor.setAttribute('target', '_blank'); }) }); </script>
document.querySelectorAll
を解釈document.querySelectorAll
の引数は CSS セレクタで指定します。その中身である
"a[href^='http']:not([href*='" + location.hostname + "'])"
を解釈していきましょう。
まず a[href^='http']
から…との記事を書いていたのですが、先に location.hostname
から。location.hostname
は「現在ページURLのホスト名」の文字列です(参考:location.hostname-JavaScriptリファレンス)。ここでは本ブログのホスト名 riocampos-tech.hatenablog.com
になります。次に、その前後をみると '" + location.hostname + "'
とあります。シングルクオートとダブルクオートとが並んでいて読みづらい上、なぜシングルクオートとダブルクオートとが並んでいるのか?と悩んでしまいます。結論から言ってしまうと、+ location.hostname
の前のダブルクオートは冒頭 a
から続く文字列を閉じるものです。CSS セレクタは当然ながら文字列なので、文字列の中にさらに文字列であるURLを引用するにはシングルクオートを使う必要があります。しかし文字列の中に引用を入れるのは従来の JavaScript では不可能だった1ので、シングルクオートとダブルクオートとを並べることになるわけです。ややこしいので、先に location.hostname
の部分を文字列にしましょう。すると[href*='riocampos-tech.hatenablog.com']
という文字列になります。CSS セレクタ全体を見直してみると
"a[href^='http']:not([href*='riocampos-tech.hatenablog.com'])"
となりました。では改めて解釈していきましょう。
まず a[href^='http']
は「a
要素のうち href
属性の値が文字列 http
から始まる要素」という意味です(参考:E[foo^="bar"]-CSS3リファレンス)。
次に :not(〜)
は「引数(〜)に該当しない要素」なので a[href^='http']:not(〜)
は「a
要素のうち href
属性の値が文字列 http
から始まり、且つ引数(〜)に該当しない要素」という意味になります2(参考:E:not(s)-CSS3リファレンス)。で、引数の部分は [href*='riocampos-tech.hatenablog.com']
となっています。ここは「href
属性の値が文字列 riocampos-tech.hatenablog.com
を含む要素」という意味です(参考:E[foo*="bar"]-CSS3リファレンス)。
まとめると「a
要素のうち href
属性の値が文字列 http
から始まり、且つhref
属性の値が文字列 riocampos-tech.hatenablog.com
を含まない要素」が document.querySelectorAll
で選び出されることが分かります。
forEach
以降を解釈(いずれ書きます)
この記事の内容は、基本的には一つ目のリンク先のままなのだけど、空白や改行を削除したり、jQuery のリンク先をはてな内にしたり、 jQuery から ES5 へ変更したり、<script>
タグの表現を変更したりヘッダじゃなくフッタへの設定に変更したり、 function を Fat arrowにしたりしてます。
じつは Document.querySelectorAll()
の返値 NodeList
は NodeList.forEach()
を使えなかったのですよ。最近のブラウザは使えるようになったようなので、それで使ってます。古いブラウザ対応は無視w (参考:NodeList.prototype.forEach() - Web APIs | MDN)
でもね。iPhone のスマホビューで見たときには別タブで開いてくれないのです…なんでなの。
jQuery の
HTML 読み込みなどの設定はスマホ用サイトだと別設定になっているし、はてなブログ PRO じゃないとスマホ用の HTML を書けないということに気付きました…うーむ。2年まとめ払いでも月額600円だから、はてなダイアリープラスの価格より大幅値上げに感じてしまうのよね…。
まあそれぞれのブログの末尾に$(document).ready
なのがスマホだとダメなときがあるという話を読んで「これは jQuery を止めちゃおう」と思って ES5 に書き換えたのにな。
<script>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>anchor.setAttribute('target','_blank'))</script>
って毎回追記しておいてもいいのだけどね。面倒だけど3。
なお、ブログ末尾に上記のスクリプトを追記するのであれば、はてなブログの設定のスクリプトは
<script>window.addEventListener("DOMContentLoaded",()=>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>{if(anchor.getAttribute('target')!=='_blank')return;anchor.setAttribute('target','_blank');}));</script>
のように target="_blank"
がある場合にはスクリプトを実行しないようにしておいたほうがいいかなと思います。