スキップしてメイン コンテンツに移動

投稿

ラベル(javascript)が付いた投稿を表示しています

帰宅した時に、Sesami4 を自動解錠するよう IFTTT で操作する

Sesami4 を IFTTT で操作する 先日、スマートロックの Sesami4 を購入した 。 使い始めて 1 ヶ月ちょいになり、不満点が出てきた。 手ぶらで解錠がロクに効かない Android のウィジェットが常時表示はウザい オートロックを有効にしてると締め出される(当たり前だよなぁ!?) と言った感じ。 この中では特に手ぶらで解錠がロクに効かないのには相当不満があった。 原因はシンプルで、BLE(Bluetooth Low Energy)が上手く動作していなかった。 観察した結果だが、動作する時はちゃんと動作するが、ダメな時はとことんダメ。 Sesami の作り込みが甘いのか、純粋に Android の反応が悪いだけなのか、どちらなのか判断は付けられない。 その両方である可能性もあるが、いずれにせよこれでは快適な生活が送れない。 Sesami は API を公開しているので、それを使ってリモートコントロールする事にした。 あ、一応 Sesami の WiFi モジュール は導入している前提。 これがないと今回の Tips は使えないので、気をつけるように。 今回は スマートロックのセサミをさらに便利にする(アレクサからパスコードレスで解錠&オートロック化) の記事をそのままパクってるだけなので、その記事を読めば概ね同じことが出来る。 Sesami API キー取得 公式ページ にアクセスし、メールアドレスを入力する。 認証コードが送られてくるので、それを入力すると API 取得画面が表示される。 スマホアプリの「このセサミの鍵をシェア」から QR コードのスクリーンショットを撮って、API 取得画面にアップロードする。 そうする事で、デバイスの UUID と SecretKey が取得出来る。 API キー デバイスの UUID デバイスの SecretKey GAS のエンドポイント認証用のハッシュ値を用意する 下記のコマンドを実行して、認証用ハッシュ値を取得する。 任意のパスワードは、IFTTT との連携に使用するので、メモしておく事 $ echo -n '任意のパスワード' | shasum -a 512 自分は WSL2 上で実行して取得した。 SHA512 Onl...

Next.js でのハマりどころ

Next.js でのハマりどころ 自分用メモの羅列 firebase用の.envファイルのパラメータ命名 NEXT_PUBLIC_FIREBASE_API_KEY="" NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN="" NEXT_PUBLIC_FIREBASE_PROJECT_ID="" NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET="" NEXT_PUBLIC_FIREBASE_MESSAGE_SENDER_ID="" NEXT_PUBLIC_FIREBASE_APP_ID="" NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID="" 先頭のprefixに必ず NEXT_PUBLIC_ をつける事。これをつけないと、Next.js内で参照する事ができない。 process.env.~でアクセスするコードを書くと分かるが、コマンド実行しているコンソール内にはきちんと設定した環境変数が出力されるが、ブラウザのコンソール内にはundefinedが出てくる。 こういう謎のprefixをつけなきゃ見えないみたいな処理が入ってるのは、フレームワークあるあるの罠である。 ロード時間に死ぬほど時間が掛かる プロジェクトに recharts を追加してからyarn devしたら、読み込みに死ぬほど時間が掛かるようになった。 具体的には、1.8Mのjsファイルを読み込むのに1分ちょい掛かるというありえない開発体験をする事に。 「nextjs development loading very slow」みたいなキーワードで検索すると、検索トップに Super slow page load times in development environment みたいなgithub discussionページが引っかかった。 これをばーっと眺めていると、どうやらGoogle ChromeのPWA用キャッシュをクリアすると早くなるらしい。 半信半疑で、Application→Application→Storage→Clear site dataをクリックしたら、見事にロード時間が改善...

Refactor Togetter auto expand.

Togetter auto expandを最近の書き方で。 らいもんさんが、 Togetter auto expand というぐりもんを書いていたので、リファクタした。 ぐりもん書いたの久々。 ただ、コード量としては増えているから、IntersectionObserverを使うよりかは、元ネタの通り、setInterval使ったほうがスマートかな。 ミニマムなIntersectionObserverのサンプルコードになるので、何かの参考になれば良い。 // ==UserScript== // @name Togetter auto expand // @description Togetterページの「この続きを読む」自動でクリック // @namespace http://sangoukan.xrea.jp/ // @match https://togetter.com/li/* // @grant none // @downloadURL https://github.com/raimon49/userscripts/raw/master/togetter_auto_expand.user.js // @updateURL https://github.com/raimon49/userscripts/raw/master/togetter_auto_expand.user.js // @noframes // @author raimon // @version 1.0.1 // ==/UserScript== (() => { function callback(entries){ entries.forEach(entry=>{ if(entry.isIntersecting){ let elem = entry.target; if( elem && typeof elem.onclick==="function"){ ...

tailwind.cssでハマった罠

tailwind.cssの罠 先日、tailwind.cssで謎(?)のバグに遭遇し、2週間くらい解決してなかったのが、つい先程解決したので、記述する。 症状 javascriptで、"py-32"クラスを追加したもの、"py-32"が効かない。 原因 HTMLに"py-32"が書かれていなかったので、 対象となるクラスがバンドルされなかった 。 対処 ダミーで適当なHTMLに適用させたいクラスを記述する。その後、必要があればjavascriptで削除する。 感想 この罠のやばい所は、 開発環境では再現しない という事。 ビルド後に発生するバグってホント、デバッグしにくいですよね。 本番環境でバンドルされているCSSを分析してようやく原因に気がついた。 冷静に考えてみると、このバンドルする際の設定は全部お任せにしているとこういう罠にハマるんだなぁと。 自前でバンドル設定を書くのが死ぬほど面倒なので、エコシステムに依存した環境構築をしたのは良いとして、こんな面倒くさいことにハマるのはなんかやだなぁ。 エコシステムは楽な分、別の場所でハマる事があるので、あんま好きじゃない。

API化したGASの高速化まとめ

API化したGASの高速化まとめ ひょんな事から、GAS経由でスプレッドシートの中身をAPI化する案件を頂き、ざっと構築したのは良いがあまりにも処理が遅すぎたので、高速化のためにやったあれやこれをまとめる。 全データ取得 まず、一番の高速化と言えば、データ取得。 for文で回してセルのデータを取るのではなく、 Sheets.Spreadsheets.Values.batchGet(sheetId, request).valueRanges みたいな感じで、ぐわっとデータを取るのが早い。 これは以前にやった事がある事だったので、基本中の基本なのだが、これだけだと高速化しなかった。 キャッシュ化 今回の案件は、複数のスプレッドシートからデータを取得して表示するという物であった。 故に、初回の実行時はどうしても何度かリクエストを飛ばす必要があった。 で、これが同じネットワーク(?)内だとある程度キャッシュが効くのだが、別のネットワークになると途端に起動が重くなるという クソ仕様 現象が生じた。 これを解決するために、色々調べた結果、 CacheService を使うと良い事が分かった。 const cache = CacheService.getUserCache(); みたいにして、後は let data = cache.get("keyName"); if( !data ){ //dataを色々処理 cache.put("keyName",JSON.stringify(data)); } と書いて対応する形にした。 今回は、APIを起動実行するユーザが一人しかいない前提なので、getUserCacheを採用したが、getDocumentCacheや、getScriptCacheとかでも全然構わない。 localStorageの採用 さらなる高速化として、localStorageを採用することにした。 これで、爆速化した。 一応、データ更新は3時間に1回という形にして、 let data = localStorage.getItem("keyName"); let dataObject; // キャッシュ時間は3時間くらい if( !data || data.expire ...

puppeteer で、ほどほどの速度で自動スクロールさせるコード

puppeteer で、ほどほどの速度で自動スクロールさせるコード puppeteer で、ほどほどの速度で目的の要素の位置に自動スクロールさせるコードを書いた。 await page.evaluate(async () => { const targetClass = ".target_class"; const hh = document.querySelector(targetClass).offsetHeight; await new Promise((resolve, reject) => { const moved = 100; let _top = 0; let timer = setInterval(() => { window.scrollBy(0, moved); _top += moved; if (_top > hh) { clearInterval(timer); resolve(); } }, 100); }); }); targetClass に、適当なセレクタを指定の事。 最初は、 await page.evaluate(async () => { const targetClass = ".target_class"; const hh = document.querySelector(targetClass).offsetHeight; window.scrollTo(0, hh); }); というシンプルなコードを書いていたのだが、これだと Intersection Observer 的な奴の処理が上手く走らなかったので、少し面倒くさいコードを書くに至った。 これならば、ちょっとずつスクロールしてくれるので、Intersection Observer に何か仕込んでいるサイトでもちゃんと動いてくれる。

electronのリリース用ファイルサイズを半分以下にした

electronのリリース用ファイルサイズを半分以下にした 本日、 きつねゆっくりリネーマーVer 0.0.2 をリリースした。 基本機能は変わっていないが、リリース用のファイルサイズを半分にした。 変更箇所 変更箇所は、package.jsonのbuild。 変更前 "files": [ "dist/**/*" ] 変更後 "files": [ "!.git", "!.dist", "dist/background.js", "dist/index.html", "dist/preload.js", "dist/assets/**/*", "node_modules", "package.json" ], 変更したのはここだけ。 以前のバージョンは、dist以下全部をビルドするようになっていたが、今回は、ビルド用のファイルを個別に指定するようにした。 node_modulesやpackage.jsonやら、色々書いているが、多分要らない。 今後、実験してこの辺はアップデートしていく予定。 推測 以前のビルド設定だと、dist以下を全部包含して作っていたため、同じファイルを2回パッキングしていた可能性がある。 ひどい。 まあ、何も知らないで作るとこうなるという話なので、もし似たような件で悩んでいる人がいたら参考にしていただければと思う。

きつねゆっくりリネーマーというツールを作った

きつねゆっくりリネーマーを作った きつねゆっくりリネーマーという名前のツールを作りました。 こちらからアクセスしてください 技術関連に関するあれやこれ 今回は、自分の主戦場でもあるJavaScriptをベースにツールを作ろうという事で、色々模索した結果 vite+TypeScript+electron という技術選定になった……が、実際にはTypeScriptはほぼ使っておらず、JavaScriptメインでの実装になってしまった。 これに関しては、今後のアップデートなどで更新出来たら良いなぁぐらいに思っている。 electronでfsなどを使うためには、色々工夫が必要で、preload.jsにcontextBridgeやらipcRendererを経由して、background.jsでデータをやりとりするみたいな感じになった。 レンダラーの所では、window.API名みたいな感じでアクセスするのだが、これの部分にはちょっと工夫が必要で、 App.tsx を見てもらえば分かるのだが、 declare global { interface Window { api?: any } } の設定と、関数内で、 if( window.api ) というチェック処理が必要になる。これをやらないとコンパイルが上手く通らない上、画面が真っ白になって動かないというバグがあった。 これは、デバッグモードでは見つけることが出来ないバグだったので、色々と辛かった。 まあ、いずれにせよ、このツールを作る事で、electronアプリの作り方を一通り体験出来たのは良かった。 nodejs周辺のライブラリを使うのにはかなり工夫が必要なのだが、一旦覚えてしまえばそこまで複雑な処理ではないので、勉強できて良かった(小並感)。 その他今後やっていきたい事 今回、ビルドしてみて改めて思ったのは、electronアプリのサイズがでかすぎるという事。 Hello,worldレベルのアプリに125Mは流石にでかすぎる。 サイズ的には30Mとか40Mくらいに抑えられるものだと思っているので、今後何かしら良い方法を知ることが出来たら、それで実装してみたいと思う。

Netlifyでnode-gypのビルドが失敗したので、その対応

netlify で node-gyp のビルドが失敗した時 node-gyp という、nodejs回りを触っていたらなんか勝手にインストールされる奴がいるんだけれど、毎度毎度ビルド回りで、困らせてくる。 今回は、netlifyでビルドしようとした時にこいつのビルドが出来なくて、困ったので、その備忘録。 自分がビルドしようとしたnode-gypのバージョンは、8.4.1(2022å¹´3月現在)。 こいつのビルドには、どうやらPython3.6以上が必要。 しかし、netlifyのデフォルトでは Python3.5.2が使われていたのでコケてしまった。 なんだこいつ。 https://docs.netlify.com/configure-builds/environment-variables/ と、 https://github.com/netlify/build-image/blob/xenial/included_software.md を見て、どうやらPYTHON_VERSIONに3.7を指定出来るようなので、Deploys > Deploy settings > Environmentを選び、PYTHON_VERSIONを追加した。 ついでに、NODE_VERSIONも今使っている16.14にアップデートしておいた。 これでビルドが上手く通った。 node-gypって何に使ってるん? node-gypって何に使ってるんでしょうね。 なんか色々入れていると気がついたら毎回入ってくる感じで、マジで捨てたい。 こいつのビルドエラーは頻繁に起こっている印象があり、開発体験を著しく悪くしているのでなるべくサクサクと倒せるようになりたい。

webpack4→webpack5をして、Module not found: Error: Can't resolveが出た場合、'html-loader'を削除しろ

webpack4→webpack5でハマった 久々のLooxUと初音ミクで行こう!の更新。皆様お久しぶりです。 今回は、webpack4からwebpack5へ移行した際にハマった出来事について記載したいと思います。 事象 Module not found: Error: Can't resolve '/manifest.json' エラーメッセージとしては、上記の様なメッセージが出ていました。 なんとなく、html-webpack-pluginで呼び出している箇所に問題がありそう。 しかし、その設定を見る限り特に変な書き方とかをしていなかったので、一体何が問題なのかしばらく分かりませんでした。 原因解明 html-webpack-pluginの templateのドキュメント を読んでいて、原因に気が付きました。 1) Don't set any loader これかー! webpack.config.jsに書いてあった、 module: { rules: [ { test: /\.html$/, loader: 'html-loader' }], }, この部分を無効化したら無事に解決しました。 いやあ、とんでもない所に落とし穴があるものです(笑)

にゃーんを更新しようとしたら色々とハマった

nyaan更新でハマった 拙作だが、 にゃ~ん というふざけたウェブサービスを作っている。 猫の画像が出てきて、ボタン(?)をクリックするとにゃーんとつぶやけるだけのシンプルなサービスである。 これを本当に久々に更新したら、色々エラーが出て、知見を得られたので、公開。 CopyWebpackPlugin の構文が変わっていた。 以前のCopyWebpackPluginは new CopyWebpackPlugin([ { from: "src/images/", to: "" }, ]); と書くことが出来たが、今はできない。 new CopyWebpackPlugin({ patterns: [ { from: "src/images/", to: "" }, ] }); と書く必要がある。 いつの間にそうなってたんだろうw 配列から、ハッシュへ。 まあこの辺はエラーメッセージなどを舐めればそこまで難しくはない。 deploy 時のエラー > webpack --config webpack.prod.config.js --mode production /opt/build/repo/node_modules/copy-webpack-plugin/node_modules/p-limit/index.js:30 } catch {} ^ SyntaxError: Unexpected token { deploy時に謎のエラーが出ていた。これは、 https://github.com/sindresorhus/p-limit/commit/b35faf54fb0871d9ae592069a18083a2ba15d8a9#diff-168726dbe96b3ce427e7fedce31bb0bc に書いてある通り、Node.js 10からは、valid syntax になったからだったようだ。 netlifyでビルドするためのNodeのバージョンを上げれば良かったので、 ここのドキュメント を参考にして、B...

Bot復活

botを復活させた Twitter、休眠アカウント削除へ 対象アカウントに12月11日までにログインするよう警告 昨日のこのニュースを受けて、そういえば動かしていない bot アカウントがあったなーと思いだして見直してみたら、2011å¹´5月13日を最後に、稼働していませんでした。 とりあえず、まずログインしてアカウント保護のために適当にツイート。 それから、当時 bot を動かしていたコードをレポジトリから発掘。subversion を使っていたことに歴史を感じます。 せっかくなので、 github の private レポジトリに移行しました。 また、当時は ruby でコード書いていたのですが、今は仕事でも使い慣れている nodejs を使い bot を書き直しました。 その bot は1時間ちょっとで完成し、自分の技術力アップと、エコシステムのありがたみを感じました。 heroku の使い方を完全に忘れていましたが、公式ドキュメントを読んでサクサクっと使えたのが本当に良かったです。 こっちの設定は思った以上に時間がかかりましたが、しっかりとデバッグ出来てよかったです。 今回新たな試みとして、 cron-job.org を使ってみることにしました。 このサービス非常に便利ですね。単にAPIを叩くだけの cron を書くよりも、URLを指定するだけ&適当な時間を設定できるので、非常に楽ちんでした。 とりあえず、まずは復活させるという目的が達成できたので、次はいくつかの機能を実装する感じでしょうかね。 今はリプライに関しては無反応なので、それらの対応を出来るようにして置きたいですね。 前のバージョンでは、sqlite3を使ってデータをローカルに保存して使っていましたが、今だったらもっとスマートに解決するようにしたいですねw

個人サイトの死

個人サイトの死 2019年は、個人サイト作成という文化が死去した年だと思っている。 かつては多くの人が個人サイトを作成していたと思う。個人サイトなんて言い方よりも、ホームページとかほめぱげとかそういった言葉の方が心に刺さるかもしれない。 Yahoo!ジオシティーズサービス終了のお知らせ 2019年の3月に最大手とも言うべきジオシティーズのサービスが終了した。 これが決め手になったが、そのずっと前からすでに個人サイトを作成することはコストの割にリターンが少ないので、多くの人が手を引いていたのではないだろうか。 個人サイトの最盛期はいつ頃だったのか覚えていないが、肌感覚では2005年の前後3年くらいが最盛期だっと思う。 ブログの台頭と入れ替わりの形で個人サイトは徐々に衰えていった。 そのブログ自身も衰退して、SNS(TwitterやLINE)に押されまくり、最終的にたどり着いているのがYoutubeのような気がしている。 現代Webで一番稼げるのはYoutubeである事に異論を唱える人は少なくないであろう。 個人サイト→ブログ→SNS→Youtubeといった流れだ。 もちろん、今でもすべてのサービスは平行で稼働していて皆様々な活用をしているが、以前のような激しい変化は減っている。 個人サイトは、構築するのが非常に大変である。HTMLとはなにか、CSSとはなにか、JavaScriptって何?クロスブラウザ?サーバ?FTP?BASIC認証??ドメイン??SSL証明書?? そう、Webのあらゆる基本を学ぶことが出来た。 ローカルで確認する際に、file:/// みたいなURIで作成して表示していたのは非常に懐かしい話だ。 C++オンリーで開発していた自分が今ではJavaScriptオンリーで開発するような環境に変わるとは、当時欠片も知らなかった。 個人サイトが死ぬ事で、Webの基本的な事柄を知らなくても簡単に情報発信できるようになった今の時代は実はとても恵まれているのかもしれない。 しかも、パソコンなしでも全部出来るようになっているのが大きい。 Youtubeの動画を撮影して、編集して、文字入れして、サムネイル作っても、スマホがあれば(時間が掛かるが)出来ないわけではない。 私がフロントエンドエンジニアとして働くきっかけになったのは、初めての転職がきっ...

webpack の babel-loader で、@babel/preset-envのオプションを指定して、useBuiltInsなどを使えるようにする

webpack の babel-loader で、@babel/preset-envのオプションを指定して、useBuiltInsなどを使えるようにする まずは、結論のコードから { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: [['@babel/preset-env', { useBuiltIns: "usage", corejs: 3 }]] } }, exclude: /node_modules/, } 以上。 以上じゃねえよ。 preset-envの部分に注目。 直感的には、 presets: ['@babel/preset-env', { useBuiltIns: "usage", corejs: 3 }] と書けば上手く行きそうなのだが、エラー吐かれます。 正しくは、上記の設定のように presets: [['@babel/preset-env', { useBuiltIns: "usage", corejs: 3 }]] と、大かっこで2回囲ってやる必要がある。 めっちゃ面倒

JavaScriptのargumentsって気持ち悪い動きをするんですね

久々のブログ 皆様お久しぶりです、Arc Cosineです。 最近は、ゲームブログばかり更新しているので、この雑ブログも閑古鳥が泣いております。 今日は珍しく技術的な話です。 JavaScriptのargumentsって、色々便利に使えるのですが、意外とその仕様をしっかりと理解していませんでした。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments 興味がある方は、↑を見てください。 見てて面白いなーと思ったのが、このコード。 function func(a) { arguments[0] = 99; // updating arguments[0] also updates a console.log(a); } func(10); // 99 お前変わるのかよwwwww function func(a) { a = 99; // updating a also updates arguments[0] console.log(arguments[0]); } func(10); // 99 こんな気持ち悪い動きもします。 aを変えているのに、arguments[0]が変わるという挙動をします。 ちなみに、デフォルト値を設定するという気持ち悪いコードを書くとこういう動きをします。 function func(a = 55) { arguments[0] = 99; // updating arguments[0] does not also update a console.log(a); } func(10); // 10 なんだよお前wwwwww いやぁ、草が生えます。 こういう謎の動きをするので、strictではない、デフォルト値を指定するという書き方は、避けたほうが良いですねー。 JavaScriptを触り続けて10年が経過しようとしていますが、こういう基本的な事でも知らないことってあるものですね。 argumentsを使うようなテクニカルなコードを書く事は滅多に無いのですが、頭の片隅に置いておくと良いでしょうね。

IE8でdocument.querySelectorが使えなかった事案発生

IE8でdocument.querySelectorが使えなかった事案発生 そもそも、今どきIE8対応とかやりたくないのですが、お客様の手前そういう事を露骨に言うことも出来ず、オブラートに包みまくって伝えたのですが、半分以上伝わってないんじゃないのかなと思っている。 さて、今回上手く動かなかったのは↓の記事に書かれている通りの条件が揃っていたからだった。 参考URL ちなみに、どんなページだったのかというと HTMLを見てみたら、こんなmetaタグが埋め込まれていました。 <meta http-equiv="X-UA-Compatible" content="IE=7" /> やめてくれ……orz 対応方法 document.querySelectorを使わない

ニコニコ大百科のネタバレ防止反転を解除するブックマークレットをちょっとだけ変えてみた

概要!!! iPhoneでニコニコ大百科を見てるとネタバレ防止反転を読むことが出来ないという悲しい事態がある。 それを回避する方法を今日たまたま見かけたので、実践してみた。 詳細ッ!!! 元ネタはこちら ニコニコ大百科のネタバレ防止反転を解除するブックマークレット で、改造したコードはこちら。元ネタはPCサイトのノードをターゲットにしていたので、僕はモバイルサイトの方のノードをターゲットにした。後、無意味に無名関数で囲って謎の汚染保護。深い意味は無い。 javascript:(function(){ $(".article [style*='color: white'],.article [style*='color: #ffffff']").css("color",""); } )() 後は↑のコードをSafariやChromeのブックマークに設置するだけ。 Google Chromeの場合、ブックマークマネージャーにモバイルのブックマークって出てくるから、そこに追加するだけでモバイルにも反映されるので、便利。 Safariはふみをさんのブログに書いてある通りにやればおk. Gooogle Chromeでブックマークレットを実行する時は、アドレスバーにタッチして、ブックマークレットの名前を入れれば良い。 僕はnetabareって名前にしたので、netabareってtypeしている。

モバイルブラウザで音が出ない時

超例外パティーン おっす、オラ開発狂。 今日も元気にデバッグしまくるぜ。 今日解決したのは超例外パターンだ。あまりにも例外的な状況だから誰の役に立つか分かんねーけど、多分誰かを救うことになると思うからここに書きなぐっておくぜ。 モバイル版Google Chrome(iOS)やAndroidのブラウザで音が鳴らない 最近、JavaScriptでvar sound = new Audio();sound.src='hoge.mp3';sound.play();みてーなコード書くんだけれど、音が鳴らない環境があってオラ超困ったんだぞ。 その環境は、Basic認証をかけてる環境だ。 おめえたちも騙されたと思ってBasic認証を書けたサーバにmp3ファイルを置いてモバイル版Google Chromeでアクセスしてみるんだ。 そもそも再生されなくて目の前が真っ白になるぞ。 こりゃ~つれ~な~、おらわくわくしてきたぞ。 解決方法はBasic認証を外すだけだ。それ以外は知らん。 この書き方疲れてきた。 ということでまとめ 基本的に、Basic認証をかけている環境では、mp3を再生できない Google ChromeはNG AndroidのブラウザもNG なぜかMobile Safariは行ける ちなみに、Opera Coastは余裕で天元突破 僕が血反吐を吐くことで誰かが幸せになるなら、それは僕にとっての幸せなのだ(ばたり

CSSStyleSheetの罠

CSSStyleSheetの罠 CSSStyleSheet - Web API インターフェイス | MDN ここをよく読むと分かるのだが、 スタイルシートが別のドメインから読み込まれていると、cssRules の呼び出しで SecurityError が発生します。 って事です。 クロスドメインでCSS読み込んで@import文を無理矢理展開しようと画策していたのですがダメポでしたね。 まあ、そんな七面倒なことをせずに素直にproxyかますか、linkタグを生成するのが正道ですね。 さて、proxy書く作業に戻ります。 今、僕はとても悲しい気持ちです。(´・ω・`)

iOS7にて、Mobile Safariのwindow.innerHeightを正しく取得する方法

久々のブログ どうも、お久しぶりです。最近、私生活やら公生活が忙しすぎてブログ書く暇がありませんでした。 今日、むちゃくちゃ感動した技術を見つけたので、それをメモ書きします。 iOS7のMobile Safari限定バグ iOS7のMobile Safariは、以前のMobile Safariと仕様が変わり、スクロールすると、上部のアドレスバーと下部の操作エリアが自動的に隠れる仕様になりました。 自動的に隠れたアドレスバーや操作エリアを再表示するためには、Mobile Safariの上部や下部を軽くタップして表示させるという動作が必要です。 今回問題となったのはこの再度アドレスバーと操作エリアを表示させた画面サイズでした。 よくあるコードですと、window.innerHeightで高さが取得出来るのですが、恐ろしいことに、この画面のサイズは、アドレスバー+操作エリアの高さを計算に入れていない値が返されるのです。 どういうことかというと、 A┌────────────┐ │アドレスバー │ B├────────────┤ │コンテンツ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ C├────────────┤ │操作エリア │ D└────────────┘ こんな感じで画面があるとすると、B-Cの高さを知りたいのに、window.innerHeightはA-Dの高さを返してくるという事です。 ついでに言うと、position:fixedでのt...