CSS selector 覚書

これで飯食っている人なら何を今更、だと思うんですけど。。。
CSS selector と JavaScript の覚書です。

昨日ボヤいた Walmart のサイトデザインが変わって、印刷した inovice のレイアウトが悲惨なことになったという件ですが、一括ダウンロードする際に、CSS を編集して保存していました。
そうすると、サイトの構成が変わったら、また一からダウンロードしなおさないといけないので、このやり方はまずいなと。そこで、ダウンロードは素のままで、それをローカルで開いた時に JavaScript で CSS を後から細工することにしました。
やることは、document.querySelector('#target').style.display = 'none' 的な感じなんですが。

まず最初のお題は、いくつかのアイテムをまとめて注文した場合、返品ボタンとかが複数表示されて、それも印刷されてしまうので まとめて 消したい、です。

先に結論を書きます。

document.querySelectorAll('.product-button-groups').forEach(e => { e.style.display = 'none'; });

ボタンは、product-button-groups というクラスなので、querySelectorAll まとめてひっかけます。

ここまではいいんですが、querySelectorAll で戻ってきた NodeList をどう回していくかというのが問題です。

ありがとう、エラい人。
自分は美しさが気に入りましたよ。
IE なにそれですし。

今までだったら、for で回すところです。
美しくないけど、何やっているかは明らかだし、ちゃんと動くし。

どういえばいいんでしょうか、便秘で溜まったものが一気に出たというか、そういうスッキリ感です。
便秘になったことはないんですけどね。

スッキリしたところ、次のお題です。
先にコードから書いちゃいます。

document.querySelectorAll('[data-automation-id=gc-payment-details] tr:nth-child(n+2)').forEach(e => { e.style.display = 'none'; });

支払い内容の表示なんですけど、table になっていて、普通はカードで払ってそれでおしまいなので、最初の tr に Total が、次の tr にカード番号が入ってきます。

ところがどっこい、最近、ギフトカードがバンドルされたお買い得商品をよく買うもので、買った以上使うわけですが、1 度に 5 枚まで使えるので、そこにさらに 5 件のカード番号が表示されて、もうトイレットペーパー占いで引き出された便所神の如く、だらだらと長いインボイスになってしまうので、2 番目以降には消えてもらおうってわけですよ。

:nth-child(n+2) でまとめてひっかけ、スッキリ。
forEach でまとめて消して、スッキリ。
ダブルスッキリ。

ダブルといえば、JB64 ですがオーディオレスなのでヘッドユニットを買わないといけないのですが、日本だと 2 DIN っていうじゃないですか。アメリカだと、double DIN といいます。
それで、ナビはもっぱらスマホのを使っているので Apple Car Play に対応していて、そのほかの下らない機能、ナビはさておき DVD だとかの光学ドライブといったもう 10 年は使っていないものがなくて、シンプルで安いものを探していたんです。

Amazon.com 売れ筋 No.1 が Sony XAV-AX1000 です。

これ、物理的なボリュームがあるし、前に USB コネクタがあるんですよ。
なもんで、USB メモリを挿すのも楽。
そして何よりも安い。
注文しようと思ったら、日本に直接出荷してくれるセラーさんが品切れしてしまいました。

それと crutchfield で適合を確認したかったんですが、そもそも SUZUKI が存在しなかったです。JB23 の情報でもあれば、付くかどうかくらいはわかると思ったんですが、JB23 を置いておけば、XAV-AX1000 単体を輸入して、動作確認をした上で、配線キットなどは JB23 と JB64 との差分で行けると判断できましたが。
なんにせよ、段取りが悪すぎました。

ステアリングリモコンに対応しているし、純正でも良かったんですけど、それはそれで、面白くないので Alpine の DAF9, フローティングビッグDA を買いました。

しかし、クソ高かったなぁ。。。

その割に、DAF9 もそうだし、純正の DA も、XAV-AX1000 も、Bluetooth 機能はあるんですが、Apple Car Play に関していえば、有線で接続しないとダメなんです。

Mini の場合、乗ると勝手に Bluetooth でペアリングして、勝手に音楽の再生(レジューム)がはじまります。
何もしないでいいんですよ。
センターには Qi の充電機能付きホルダがありますから、XR 以外だったら、そこにセットできます。
自分も 5 号も XR だからセットできませんけど。
なので、それが当たり前だと思っていたのですが、随分と完成度が低い気がしますね。

あと、「ビッグだ」なんて、安直な名前だと思ってたんですけど、

DA = ディスプレイオーディオだったんですね。。。

スッキリと言えば、愛媛の愛すべきクソ CM 企業、たかだ引越センターさんですよ。
スッキリする(?)CM を全国の皆々様にみていただきたいところなんですが、なんと非公開になってしまいました。
ネタバレするので、一応伏せ字にしときますけど。。。

逆に、全くスッキリしないのがコレ。

なんなんですが、このブ男は!
外人さんたちも激おこデス!
なかには、

ひっこシコシコしたかだ

という突っ込みまで入る始末。。。

えっと、なんの話でしたっけ?
CSS selector の話でした。

まあ、ここを見ろで終わってしまう話でもあるんですが。。。

それで、消えてもらう場合ですが、CSS selector でやる場合は、

visibility:hiddenは名前の通り、要素はあるけど見えない状態。
display:noneは、要素も取得されず、完全にその場にない扱い。

の違いがあって、見えなくする(場所は確保されている)のと、全くない場合と 2 パターンあるので、レイアウトの崩れ具合によりどっちがいいってのは変わるわけです。

ところで、querySelector でひっかけた要素に完全に消えてもらう場合、どうするのかという話です。
child.parentNode.removeChild(child); しないといけない。

[document.querySelector].forEach(e => { e.parentNode.removeChild(e); }) みたいな?
これだと e に代入しているから同じだし、まあ All よりも [] で一文字減ったというかなんというか。

逆に、querySelector だと、引っかかる要素がなかったときに、null が戻るもんだから、引っ掛からなかったらそこでエラーが起こって後の処理が中断されてしまうんです。

TypeError: null is not an object (evaluating 'document.querySelector('foo').style')

まあ、それはそれで、Knuth がエラーが起こると塗りつぶして文章を書きなさせるように、不都合を無かったことにしないほうがいいのかなとも思うんですが。

try { /* some stuffs here */ } catch { document.body.style.backgroundColor = 'red' }

この作業自体がとても美しくないことに起因している対症療法であるわけで、適当に済ませておこうと思います。

不良品撲滅!

FISKARS の砥石なんですけど、意外と不良率の高い商品なのです。

不良のパターンとしては、よくある順で、

  • 滑り止めが取れて数が足りずガタガタする
  • 砥石のカバーの爪が折れている
  • 砥石が入ってない

なんですが、輸送中の事故なら、箱の中に壊れた残骸とかありそうなものなんですが、箱に穴もなく残骸もない、っていうのが毎度のパターンです。

それで、当然検品しているんですが、Amazon の場合は袋を作って包んでいたんですが、直送する場合には、かなり手間がかかるので省いていたんです。

プチプチ封筒に入れて送るのですから、もし事故があればわかると思うわけですよ。
ところが、それでも事故が起こったもんですから、念には念を入れて、袋に入れることにしたわけです。

ざっと寸法を測って注文したら。。。写真の有様です。
ピッタリすぎて、蓋ができません。。。

なんとも。

そんなこんなで、今日の出荷は 1 パレットのみでした。

納品のラベル作成スクリプトをちょっと更新してたら、出荷の締め切りは 18:30 なんですが、18:20 くらいになってしまいました。

それで、ダンボールの話になるんですが、輸送箱の重量やサイズを入力しないといけないのですが、これがものすごくかったるいのです。

写真の箱だと、9″ x 9″ x 7″ ってことがわかるんですが、入力フィールドが 3 つに分かれているし、cm なのでいちいち変換しないといけなくてかったるくて仕方ない。

実際、納品のデータを作るのに小一時間かかっていますし、ミスがあると送料で莫大な損が出ますので、ものすごくストレスなんです。

作業のやり方自体に詰めて、データはアップローできるようなので、自前のシステムを構築して行こうかと思います。
ローマは一日にして成らず。
コツコツ頑張らないと。。。

それと、輸出書類の件。
Save as PDF で保存しないことにはどうにもならないので、重い腰を上げて書き直しました。

まあ、世界狭いんですよね、Mac 界隈は。
木下さん、お世話になりました。

書いてある通りなんですが、要素をひたすら every UI element で調べまくる、これで解決です。

例えば画像の状態の場合、開いているウインドウが window 1, そこに印刷のモーダルダイアログが出てますが、これは sheet 1 of window 1 となります。

PDF の部分ですが、これは menu button "PDF" で、画面の状態にするにはクリックしないといけません。
クリックする click menu button "PDF" と、メニューが表示され、選択可能になります。
click menu item "Save as PDF" of menu of menu button "PDF"

そうすると、さらにモーダルダイアログが出てきて、保存場所を選択できるんですが、これは sheet 1 of window 1 になるんです。ややこしい。

ここでは keystroke "g" using {command down, shift down} すると、フルパスが入力できるようになるので、パスを keystroke で入力した後に Save ボタンをクリックしてやると、問題なく保存されます。
ただし、ファイルが存在するややこしいので、事前に保存先の PDF は掃除しておきます。

というわけで、every UI element で調べまくる、という気づきがあり、なんとか解決することができました。

一難去ってまた一難、今度は Walmart がサイトのデザインが変わって、レイアウトが崩れまくってます。。。
ボチボチ頑張ります。

Safari の Export as PDF と Print からの Save as PDF

大ハマりです。

輸出のためのインボイスをまとめているんですが、結構枚数があるので、半自動処理をしています。

これがかなり曲者というか、トリッキーというかなんですが、流れとしては、

  • 倉庫にある品物のうち、積み込むもののインボイス番号をピックアップする
  • インボイス番号から、Amazon 等での注文だと判明したもの(日用品, 例えば洗剤など)の invoice を Safari で表示, 一旦 HTML としてローカルに保存する
  • ローカルに保存した HTML のうち不要なものを CSS を細工して取り除く(ヘッダやふった、ロゴなど)
  • Export as PDF を使い PDF に変換して保存する
  • 各インボイス番号に基づきソートし、連番を振った上で、FPDF を使い 1 ファイルにまとめる

って感じなんです。

Amazon とか、まあその辺での小物の買い物は、次のような理由でものすごく数が多いので、いちいち人力でやっていたら、大変だし、ミスが起こります。
なので、自動化しているんですが。。。

  • 洗剤やケミカル類, おにゃー様のグッズなどは、Subscribe & Save という定期注文で、1 アイテムごとにインボイスができるため、10 アイテムを定期注文しているなら、10 件のインボイスが発生する
  • Subscribe & Save は、同じアイテムを 2 個買うと、1 件の定期注文とカウントされるけど、1 アイテムづつを 2 件定期注文すると、注文件数に下駄をはかせることができ、割引率がアップ
  • また、数が多いときは、数量変更だと、いちいち変更作業が必要だけど、全部ならスキップをワンクリックするだけで良いので楽

ぱっと見はうまく動いていたんです、ぱっと見は。

問題は、表題の通りなんですが、Export as PDF と Print からの Save as PDF の違いです。

本当は、Print からの Save as PDF で PDF に変換したかったんですが、プリントダイアログの操作をしないといけなくて、この部分が不安定だったんで、それを省略できる Export as PDF で処理していました。

このところずっとこれで問題なく動いていたんですが、出来上がった PDF の用紙サイズがおかしなことになっているのです。
インスペクタで見ると、Paper size: 40.19 x 23.32cm となっています。
これを A4 サイズにすると、横 210mm x縦 297mm なので、右半分が欠落してしまいます。

当たり前ですが、Print からの Save as PDF の場合、用紙サイズの設定ができるので、このような問題は起こりません。

で、なんで一旦 HTML で保存をするのか、というと、Amazon の側が当然セキュリティのため、暗号通信になっているので、wget だとかそこらへんでゴニョゴニョできそうになかったため、です。

次に HTML から PDF の変換を、それこそ FPDF でやれよ、って話ですが、JavaScript やら CSS でゴニョゴニョしているため、レイアウトが崩れすぎて使い物にならなかったため、です。
Acrobat を使ったらできるんだろうか。。。持ってないけど。

しかしまあ、個人事業者の方で、こういう税金を払う時に提出しないといけないインボイス類って、どうやってるんでしょうかね。

というわけで、丸一日かかっても解決できませんでしたので、今回は人力で Print からの Save as PDF での変換作業で凌ぎたいと思います。

それはそうと、次の Lodge 製品の仕入れの件なんですが、今まではバラバラというか、一個一個の荷物として倉庫に搬入してもらい、それをこちらで輸出用の梱包にまとめていたんです。
ただ、この方法だと輸送コストが嵩む上、紛失や破損、あとそれらの管理のコストもかなりかかるし、Lodge 製品もある程度売れるようになってきたので、量をまとめて注文をしようかなと思うわけです。

それで、担当者が知らない単語がでてきたのですが、

ということのようです。

  • MOQ Minimum Order Quantity 最低注文数
  • SPQ Standard Packing Quantity 最小発注単位
  • SNP Standard Number of Package 標準の梱包の数=「出荷梱包単位」

さて、SNP ですが、例えば Lodge の製品で言えば、L8SK3 などは複数枚, たしか 3 枚で 1 つの箱に入っているんです。
その場合、SNP = 3 なのかなと思うわけです。
ただ、その箱が本当に最終の箱か、とも思うんですが、基本的にある程度の大きさがあり、当然に、鉄なので重たいので、3 枚入りの箱を、さらに大きな箱で梱包するのかという疑問なんですが、以前紹介した Lodge の工場での生産風景で、出荷時にパレットにはい付けして、ストレッチフィルムで梱包している様子が見て取れますが、このパレット 1 枚、これも SNP といえば、SNP じゃないの、って話です。
さらに言えば、パレットにきれいに積みつけられる数、1 段のですよ、これも SNP といえば SNP ではないかと。

うちの標準の梱包サイズで言えば、L8SK3 は LCC3 と共通の箱を使い、1 箱 5 枚で再梱包しています。
再梱包する理由は、L8SK3 には外箱がないため、Amazon で保管されている際に、

  • 1 アイテムがどこまでか範囲をはっきりさせるため
  • 商品を保護するため

1 アイテムごとに箱に入れるか、ビニール袋等で個別に梱包し、FBA ラベルを貼り付けることを求められるためです。

厳密に言えば、この作業はメーカーバーコードで納品すれば省略できますが、手間暇かけて丁寧に検品して、丁寧に梱包してこそ差別化できる わけでし、値段とその部分でしか差別化はできませんから、ここが自分の唯一の仕事と言っても過言ではありません。

で、箱の寸法ですが、B4-80 と同じくらいなんですが、長さ 375 × 幅 265mm(内寸)なので、400 x 300 といったところです。

写真は、保管のために倉庫内で積んである様子で、棒積みになっています。
この後、輸送のために、交互の煉瓦積みに積みなおししましたが。

要するに保管時には、ダンボールの強度を優先して、劣化を避けるために低く積んでおくわけです。
輸送の際には、特にこの箱は輸送専用で、Amazon に到着したら破棄されて、お客様にお届けするものではないので、到着まで持てば良いので、荷崩れせず、かつ、スペース効率の良い積み方に切り替える、というわけです。
写真の量で 3 x 3 で 9 箱、入り数が 5 ですから、一箱 15 キロはないですが、一つ 5 pounds なので、10kg ちょっとですね。なので、1 段で 100kg くらいです。
4 段積めば、一番下の段には 30kg 以上乗っているのですから、小学生くらいの子供が踏み台に使っているようなものです。
なので、ちゃんと考えないと、すぐに箱がダメになってしまうんです。
箱は 100 円近くしますので、パレット一つあたり、梱包の材料代だけで何千円もかかっているんです。

もちろん、LCC3 のように積み上げても、製品全体で重量を受け止めることができ、ダンボールが痛まない場合、また、LCC3 の場合、普通の茶色の箱と、カラー印刷の化粧箱とバリエーションがあるんですが、カラー印刷はコートされているのか、とてもとても滑りやすいため、そもそも棒積みで何段か積んだら、リフトが止まっただけで前方に滑り落ちかねないので、こういうものはシュリンクフィルムを軽く巻きつけておくと、フィルム同士が接すると滑り止めにもなるので、輸送ラベルからの保護も兼ねて、シュリンクフィルムを巻くようにしています。

えらく話が脱線しましたが、アメリカのパレットは、40″ x 48″ なので、1,000 x 1,200mm といったところなので、LCC 3 の箱なら、煉瓦積みで 300 x 400 が 4 個 x 1 列、400 x 300 が 3 個 x 2 列で、10 個/段, ということになるんじゃないかなと思うわけです。

ただ、最初から色々と細かくいいすぎるのもアレかと思うわけで、向こうも素人ではないというよりも、こちらよりも経験も知識もあるだろうから、まずはやってみて、問題が出たら煮詰めていけばいいんじゃないかなと思います。
まあ、結構、自分のやり方に固執して、それ以外はできない、という人もいるというか、そういう人の方が多いんで、問題が出ても解決できないってのは往々にしてあるパターンだったりもするんですが。

案ずるより産むが易しともいうし、とにかくやってみようと思います。