たった3行コピペするだけで可愛いポップアップが表示できる tippy.js

HTMLでサイトを作ってると、ポップアップ表示で説明を入れたい時がある。
とりあえず標準のalert('hello')とか使うけど、見た目がダサすぎる。
作っているのがサンプルアプリだとしても許せないレベル。

で、イイ感じのポップアップをalertメソッドくらい簡単に表示できるライブラリないかなぁと思って調べたら"tippy.js"を見つけました。

f:id:naosim:20200523211309p:plain
こんなポップアップがたった3行のコピペで表示できる。
デザインも良くて、カスタマイズ性も高く、ドキュメントも充実してて使いやすいライブラリだったので紹介します。

tippy.js

f:id:naosim:20200524065810p:plain

公式サイト: Tippy.js - Tooltip, Popover, Dropdown, and Menu Library
github: atomiks/tippyjs: Tooltip, popover, dropdown, and menu library

Webの完全なツールチップ、ポップオーバー、ドロップダウン、およびメニューソリューション

とりあえずアイコンが可愛い。

とりあえず表示するなら3行コピペでOK

クッソ簡単。 例えば

<div id="myContent">hello</div>

という部分にマウスオーバーしたときにポップアップを表示をしたいなら
まずCDNからのJSの読み込みを2行コピペ。

<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>

jsに実装をコピペ。

tippy('#myContent', {content: "I'm a Tippy tooltip!"});

はい。完成。
指定したのはdiv要素へのセレクターと表示するテキストのみ。
↓動作確認用のページで"hello"にカーソルを乗せてみてください。

See the Pen tippy.js sample by なおしむ (@naosim) on CodePen.

簡単すぎる!
ちなみにjquery等へのライブラリ依存もないです。ほんとに上記のコピペだけで完結。

カスタマイズも豊富

このライブラリ、簡単に使えるだけでなくカスタマイズもめちゃくちゃ豊富なんです。
いくつか利用頻度の高そうなものを紹介します。

クリックで表示する

ポップアップ表示はデフォルトはマウスオーバーですが、クリック時に表示できるようにします。 先ほどのtippyメソッドにtriggerパラメータを追加するだけ。

tippy('#myContent', {content: "I'm a Tippy tooltip!", trigger: 'click'}); // triggerを追加

このようにtippyのカスタマイズは基本的にパラメータを追加するだけ。簡単。

ポップアップを出す位置を変える

デフォルトは上側にポップアップが表示されますが、これも変更可能です。 方法はplacementを追加するだけ。例えば右側に表示したいならこう。

tippy('#myContent', {content: "I'm a Tippy tooltip!", placement: 'right'}); // placementを追加

設定値は他にもたくさんあります。いろいろ使ってみると楽しい。
- top - top-start - top-end - right - right-start - right-end - bottom - bottom-start - bottom-end - left - left-start - left-end - auto - auto-start - auto-end

ポップアップにHTMLを表示する

デフォルトではポップアップのテキストに改行を入れられません。理由はテキストにHTMLが使えず<BR>タグが使えないから。これもパラメータ追加で解決できます。痒いところに手が届いててすごい。

tippy('#myContent', {content: "I'm a Tippy tooltip!", allowHTML: true}); // allowHTMLを追加

AJAXを使うなどマニアックなカスタマイズも

公式サイトを眺めていたら、ポップアップ時にAJAXで画像を読み込んで表示するサンプルが出てきた。
そんなことまでできるのか。。
すごい。。
AJAX | Tippy.js

まとめ

コードを3行コピペだけでポップアップ表示ができるtippy.jsを紹介しました。
簡単で便利すぎるライブラリなので、知っておいて損はないですね。

1次元オセロの問題

こんにちは。
今日はひさしぶりにプログラミングの問題です。題材はオセロゲーム。
オセロゲームといえば8x8の2次元の盤面に白と黒の石をおいていくゲームですが、今日はそれを1次元にしたようなお題です。

お題

f:id:naosim:20200502060925p:plain 8x1の盤を使ってオセロをする。
盤面に白と黒の石が置かれている(上図)。
これに白の石を置く。
指定した座標に白の石を置いたときに、オセロのルールにしたがって黒の石がひっくり返った後の盤面を返す関数を作りたい。
下記のプログラムの// TODO 実装の部分にプログラムを下記、この関数を完成させてください。(TODO以外の部分に関数やクラスを作っても良いです。)

続きを読む

【js】落とし穴にハマるな!Dateクラスで日付を操作する技 5選

javascriptの標準ライブラリで悪名高いDateクラス。
通常はmoment.jsなどのラッパーライブラリを使って安全に作りますが、ちょっとしたスクリプトくらいだとライブラリは使わずにスクラッチで書きます。
そんな時に使える日付操作周りのTipsを列挙して解説していきます。 日付操作の解説の中でいくつか落とし穴があるので、それについても解説します。

紹介する日付操作一覧

  • 今日の日付を取得する
  • 明日の日付を取得する
  • 今週の火曜日を取得する
  • 先月末を取得する
  • 今月末を取得する

今日の日付を取得する

Dateは日付と時刻を両方含んだクラスです。
そこから時刻を削り、日付のみを抽出します。

new Date(new Date().toLocaleDateString())

解説

Dateのコンストラク

まずはDateのコンストラクタから解説します。 コンストラクタにはざっくり2種類あります。それは引数ありとなしです。

引数なしの場合、現在日時が取得できる

現在日時はDateのコンストラクタを引数なしで呼び出せば生成できます。

var now = new Date();

引数ありの場合、指定した日時が取得できる

引数ありの場合は、指定した日付が取得できます。指定の仕方は様々ありますが、new Date('2020/3/24')のように日付をyyyy/mm/ddの形式で指定すると日付のみで生成できます。

以上より、今回目的とする「今日の日付」を取得すためには、Dateの引数なしコンストラクタで現在日時を取得し、それをyyyy/mm/ddの形式の文字列に変換して、Dateの引数ありコンストラクタに渡せばOKです。

日時からyyyy/mm/ddを取り出す

DateクラスにはtoLocaleDateString()というメソッドがあります。 このメソッドを呼び出すとyyyy/mm/ddの形式で返ってきます。

まとめ

以上をまとめると下記のようになります。

var now = new Date();// 現在日時のDate生成
var todayStr = now.toLocaleDateString(); // yyyy/mm/ddの形式で取得
var today = new Date(todayStr); // 日付だけのDate生成

これで今日の日付が取得できます。 これを1行で書いたのが冒頭の

new Date(new Date().toLocaleDateString())

です。

落とし穴: 日付をハイフン区切りにすると死ぬ

Date生成で日付をスラッシュ区切りではなくハイフン区切りで書くことがあります。たとえばnew Date('2020-03-24')のように。
これでDateを生成すると結果は「2020年3月24日の午前9時」になります。「9時ってなんだよ!イギリスかよ!」て思いますね。。
一方new Date('2020-3-24')のように月や日付をゼロ埋めしない場合は日本時間で「2020年3月24日の午前0時」になります。
つまりゼロ埋めの有無で結果が変わるんです。
ちなみに例えば2020/10/10のように月も日も2桁の値を指定されたら、これがゼロ埋めされてるか判別できないのですが、この場合は「ゼロ埋めあり」の判定になり、イギリス時間になります。 なのでnew Date('2020/10/9')は日本時間ですが、翌日のnew Date('2020/10/10')はイギリス時間になります。
怖すぎる。。
区切り文字周辺の挙動は怪しいの以下にまとめておきます。

new Date()の引数 結果
2020/1/1 日本時間
2020/01/01 日本時間
2020-1-1 日本時間
2020-01-01 イギリス時間
2020-01-01 00:00 日本時間

(ゼロ埋めアリでも時刻を指定すると日本時間になるのか...)

とりあえずスラッシュ区切りにしておけば安心だ!

明日の日付を取得する

今日の日付取得を応用すれば明日の日付が取得できます。

var d = new Date(new Date().toLocaleDateString())
d.setDate(d.getDate() + 1)

1行目は先ほどの「今日の日付」です。 2行目を解説します。

解説

date.getDate()

2行目の括弧内にあるd.getDate()では今日の日が取得できます。
今日が3/24ならば24が取得できます。
これに1を加えて、日付を更新するメソッドsetDate()に渡します。

date.setDate()

最後にd.setDate()の部分です。setDate()は日付を更新します。
引数に月の末日よりも大きな値が来た場合は年や月をいい感じに更新してくれます。
例えば12月32日を指定すると、翌年の1月1日にしてくれます。

var d = new Date('2019/12/31') // 12月
d.setDate(32)` // => 2020/1/1

まとめ

冒頭のプログラムは、今日の日付が入っている変数dから、getDate()で日を取り出して1を加え、setDate()に渡すことで、明日の日付を取得しています。

今週の火曜日を取得する

次は先ほどのsetDate()の応用編です。 今週の特定の曜日を取得します。今回は例として火曜日を取得します。

取得例:

  • 現在が2020/3/25(水)ならば2020/3/24(火)が取れる
  • 現在が2020/3/29(日)ならば2020/3/31(火)が取れる
var d = new Date(new Date().toLocaleDateString())
d.setDate(d.getDate() + 2 - d.getDay())

解説

1行目の日付取得、2行目のsetDateによる日の更新は今まで解説した通りなので省略します。 ここでは2行目のsetDateの中身を解説します。

date.getDay()

date.getDay()で曜日が数値で取得できます。 数値は日曜日なら0、月曜日なら1、...土曜日なら6です。

火曜日までの日数

括弧内の2 - d.getDay()は何をしているのか? まず2は火曜日という意味です。 そこから今日の曜日を引くと火曜日までの日数を計算しています。 例えば今日が日曜日(0)ならば 2 - 0 で2日、今日が金曜日ならば 2 - 5で-3日です。 これを現在の日に加える(または引く)と火曜日の日付が取得できます。

まとめ

getDay()で曜日を数値で取得し、特定の曜日から日数を計算することにより、今週の特定の曜日が取得できました。 プログラムの2の部分を他の数値に変えると、別の曜日を取得できます。

先月末を取得する

var d = new Date(new Date().toLocaleDateString())
d.setDate(0)

解説

「明日の日付」の解説でd.setDate()に月末よりも大きな値を入れた場合にいい感じにしてくれる話を書きましたが、0やマイナス値のような月初よりも小さい値を入れた場合もいい感じにしてくれます。
例えば2020年1月0日は2019年12月31日になります。
つまり0日は先月末の意味になります。
なので現在の日付に対してsetDate(0)をすると先月の末日が取得できます。

今月末を取得する

先月末を応用して、「来月の前の月の月末」を取得すれば今月末になります。

var d = new Date(new Date().toLocaleDateString())
d.setDate(1)
d.setMonth(d.getMonth() + 1)
d.setDate(0)

解説

2行目のsetDate(1)は「ミソ」なのでちょっと飛ばして、3行目から解説します。

date.getMonth()

date.getMonth()で月を数値で取得します。
数値は1月は0、2月は1、...、12月は11になります。0から始まるところが特徴的です。

date.setMonth()

date.getMonth()で月を指定できます。-1や13のようなありえない月を入れてもいい感じにしてくれます。 なので

d.setMonth(d.getMonth() + 1)

の部分では括弧内で今月を取得し、それに1を加えて、setMonth()に渡すことで「来月」にしています。 この来月に対して「先月末」を意味するsetDate(0)をすることにより、「今月末」を取得できます。

落とし穴: getMonth() + 1が2ヶ月後になる

実は上記のやり方には問題があります。
たとえば現在が2020/1/31の場合、今月に1を加えると、2020/2/31となり、2月に31日は無いので、結果は2020/3/2になります。この3/2対してsetDate(0)をすると2月末になり、期待した1月末になりません。
つまり、現在の日が29, 30, 31のような、月によってあったりなかったりする日付の場合にバグになります。 この問題を解決するためには、日を安全な1日に変更しておけばOKです。それが2行目のsetDate(1)です。

まとめ

現在の日を今月の初日に変更し、来月を取得し、そこから先月末を取得することにより、今月末を取得できます。

全体まとめ

今回はDateから様々な日付を取得する方法を列挙しつつ、いくつかDateのハマりポイントも紹介しました。
jsのDateは噛めば噛むほどツラ味がでるな...ライブラリ使おうw
それではまたー。

androidの音声読み上げ機能でkindle本がガンガン読める

読書は眠くなる

今年度は職場のミッションが変化した影響で今までやったことない仕事をたくさんしています。
未経験の仕事を闇雲にやるのは非効率なので、先人の知恵を学ぶべく、読書をたくさんするようにしています。

読書をする場所はいつも通勤の電車の中です。
電車に乗ったらとりあえずandroidkindleアプリを起動して本を読み始めます。
...が...
読み始めて10分くらいたつと急に眠くなってくる。。
本の内容は面白いのに...目が勝手に閉じていく。。
こんなことを毎日繰り返しているので1冊読み終えるのに2週間くらいかかってしまう。。

もっと早く読めるようにしたいなぁと思いつつ、youtubeを見ていたらこんな動画を見つけました。

勝間さんのyoutube動画「勝間和代の、Androidトークバック機能で、Kindle本を耳で聞こう!!」


勝間和代の、Androidのトークバック機能で、Kindle本を耳で聞こう!!

勝間和代さんは、効率的に料理をする方法や年収UPの秘訣などを毎日10分程度の動画でアップしている評論家です。
上に載せた動画では、androidに標準搭載のtalkbackというテキストの音声読み上げ機能を使ってkindle本の内容を読ませて、それを聞くと読書が効率的にできるという話です。
勝間さん曰く「最近のandroidは音声がとても聞き取りやすく、機能的にも使いやすい。iPhone等にも同等の機能があるが総合的にはandroidが良い」とのことです。

これは試さないわけにはいかないと思い、早速やってみました。

読んだ本はコレ。

しっかり! まとまった! 文章を書く

しっかり! まとまった! 文章を書く

私は文章作成が苦手なので、この本は苦手分野の本です。
つまり間違いなく眠くなる本です。
これを音声読み上げを使って読書(?)してみました。
そしたら...
なんと...
たった2日で読めた!マジ革命!

音声読み上げ読書がすごい

眠くならない

目で読む読書は、目が少しでも疲れてるとすぐ眠くなってきます。
特に帰宅時は仕事終わりで疲れてるので読書がきついです。
けど音声を聞くだけなら疲れていても問題なし。
ラジオを聞いてる気分でサクサク読めます(聞けます)

歩いてる時も読める

私は通勤時に一駅分歩くようにしています。
混雑した電車が苦手なのと、気分転換のためです。
音声読み上げだと、この歩いてる時間でも読書が可能です。
本をたった2日で読めた理由はコレです。
通勤時間のすべてを読書に当てれるため、電車の中だけの読書と比べて読書の時間を絶対的に増やせます。

無料

こんな素晴らしい機能が無料で使える。
androidすごい。googleありがとう。

ただしtalkbackの操作はツライ

基本的にいいこと尽くしですが、悪いこともあります。
それはtalkback機能の操作性の悪さです。
talkbackがそもそもユーザ補助の機能でkindleを読み上げるための機能ではないので仕方がないけど。。
慣れるまでは試練です。

まとめ

androidの音声読み上げ機能を使ってkindle本を読むと眠くならずにガンガン読めて最高。
kindle unlimitedの本を全部読めそうな勢いだ。

スタンディングデスクのLevit8を紙で作ってみた

スタンディングデスクがほしいと思ってググったら、折りたたみ式の折り紙みたいなやつが出てきました。


How to: Fold/Unfold the Levit8

良さそうだけど、強度とか気になる。

てか自分で作れば良くね? と思ってとりあえず紙で作ってみた。

台の作り方

適当なカードを4枚用意する

f:id:naosim:20200201144421j:plain

カードをくっつける

セロテープでエイ! f:id:naosim:20200201144510j:plain

対角線に線を引く

線の方向は全部同じでOK f:id:naosim:20200201144542j:plain

裏返して折り目をつける

対角線は全部谷折りでOK f:id:naosim:20200201144637j:plain

両端をくっつける

ここで少し注意。
両端をぴったりくっつけてしまうと、折りたたんで収納する時に紙の厚さでうまく折りたためない。なので写真のようにちょっと隙間を開けてくっつける。
f:id:naosim:20200201144721j:plain

完成

折りたたんだ状態から台にするまでの工程はこちら。 f:id:naosim:20200201145408g:plain
できたーーー!
思ったより簡単だった。

紙の縦横比はなんでもOK

家にあった適当な紙でうまくいったので、たぶん縦横比はなんでもいいと思う。

強度はまぁまぁ

強度を試すためにいろんなものを置いてみた。 chromebookがギリギリ置けた。

f:id:naosim:20200201150247j:plain chromebookの重量に必死で耐える台

ただ最終的に台の角の部分から崩壊した。
弱点は角。
本気で台を作るときは角の強度を上げる工夫が必要そう。
とりあえず次回はダンボールバージョンを作って運用してみようかな。 f:id:naosim:20200201152136j:plain

【スプレッドシート】おじさん専用!予算管理用日付関数

こんにちは。
Googleスプレッドシートで予算管理をしようと企むオジサンです。
予算管理では様々な日付でグルーピンが必要になります。
たとえば年度ごとに集計とか、四半期ごとに集計とか...
そのために「2019/01/01」のような日付を「FY2018」みたいな値に変換したいです。
具体的には↓これくらいのケースに変換したい。

2019/01/01に対しての変換

ケース
年度 FY2018
半期 FY2018下期
四半期 FY2018_4Q
年月 201901

で、これができるカスタム関数作った。
その名もcomDate()。なんとなく会社の日付だから。
もっと良い名前あったら教えてください。

利用例

使い方について細かい話をしてもしょうがないので具体的な利用例で説明します。
まずこんな感じの家計簿があったとします。

f:id:naosim:20191123160659p:plain

支出日と支出額が書いてあるテーブルです。

これに対してC1のセルにこんな風に記述します。

=comDate(A:A,"年度,半期,四半期,年月")

第1引数は支出日の列、第2引数は変換タイプです。
これを実行するとこうなる!

f:id:naosim:20191123160828p:plain

日付がいろんな値に変換されてる!

この表を使って、年度別に集計してみる。
こうゆうときはquery関数が便利。

=query(B:C,"select C, sum(B) where C != '' group by C")

これを実行すると

f:id:naosim:20191123160852p:plain

キターーー!
オジサンの効率化完了。

ソース

ソースはここに置いておきます。
まだまだ改良の余地があるので参考までに。

ではまた。

【スプレッドシート】カスタム関数を作る

GoogleスプレッドシートはGAS側に定義した関数(カスタム関数)を呼び出すことができます。
これを使いこなせたら最強だなと思ったのでいろいろ調べました。

GASに定義したカスタム関数を呼ぶ

GAS側に

function hello() {
  return 'hello';
}

という関数があるとしたら、シートには

=hello()

と書けば呼び出せます。
上記の結果としてhelloと表示されます。

f:id:naosim:20191123150855p:plain

簡単すぎる!

カスタム関数に引数を渡す

カスタム関数には引数も渡せます。

続きを読む