WordPressでjQueryコードが動かない人へ
こんにちは。入澤です。
代表曰く「ラーメンブログとなりつつある現況を打破してほしい」ということで、唐突ではありますがWeb(WordPress×jQuery)のお話をしたいと思います。ちなみに私が最近美味しいと思ったカップ麺はマルちゃんのでかまる 濃厚コク塩ワンタン麺です。
さあレッツゴー。
○が1つ以上の方は読み進めて下さい
1, WordPressテーマファイル「header.php」の「<head>」タグ内にjQueryコードを記述しているが動かない
2, 動かないのはjQueryのバージョンが問題では?と各プラグインコードの直前にjQuery(バージョン違い)を追加している(結果動作したりしなかったり)
3, 「prototype.js」絡みのコードを入れたらjQueryが死んだ
4, 別に今直面している問題はないが、「(WordPressサイトに)画像スライダー追加しといて」「あとスクロールしたらサイドバーをなめらかに後追いで」と言われると心拍数が上がり極度の息切れをする
よくある間違った書き方 – header.phpにて
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script type="text/javascript" src="/js/jquery.slider.min.js"></script> <link href="/jquery.slider.css" rel="stylesheet" type="text/css" /> <script type="text/javascript"> $(function(){ $('#slider_text').slider({ showControls: false, autoplay: true, showPosition: true, hoverPause: true, wait: 4500, fade: 700, direction: "left" }); });
1行目・5行目がアウト!!
※1行目は「wp_head()」でjQueryが既にコールされている場合アウトです。よく分からなければそのまま進みましょう。
直します。
//削除 <script type="text/javascript" src="/js/jquery.slider.min.js"></script> <link href="/jquery.slider.css" rel="stylesheet" type="text/css" /> <script type="text/javascript"> jQuery(function($){ $('#slider_text').slider({ showControls: false, autoplay: true, showPosition: true, hoverPause: true, wait: 4500, fade: 700, direction: "left" }); });
5行目のようなjQuery関数の書き出しに関して、「うちのとは書き方違う!」という方。大丈夫です、以下をご覧ください。
時間がない人用、ワンポイント講座
これでダメなら問題は多分相当深刻だ!
【WordPressでのダメなjQuery関数の囲み方 – 代表的4パターン】
<script type="text/javascript"> $(document).ready(function(){ //$使えないよー //処理 - 実行タイミング:HTML読み込み完了時 }); $().ready(function(){ //$使えないよー //処理 - 実行タイミング:HTML読み込み完了時 }); $(function(){ //$使えないよー //処理 - 実行タイミング:HTML読み込み完了時 }); (function(){ //$使えないよー //処理 - 実行タイミング:script読み込み時 })(); </script>
それぞれ書き換えると以下
<script type="text/javascript"> jQuery(document).ready(function($){ //この中で$使えるよー //処理 - 実行タイミング:HTML読み込み完了時 }); jQuery().ready(function($){ //この中で$使えるよー //処理 - 実行タイミング:HTML読み込み完了時 }); jQuery(function($){ //この中で$使えるよー //処理 - 実行タイミング:HTML読み込み完了時 }); (function($){ //この中で$使えるよー //処理 - 実行タイミング:script読み込み時 })(jQuery); </script>
上3つは意味が同じ書き方(7・12行目が2行目の省略形)。「$」を「jQuery」に変更し、「function()」を「function($)」にします。
下1つは「function()」を「function($)」に、最後の「()」を「(jQuery)」にします。
タイプ別、モアワンポイント講座
1, の方、直りましたか?そうでしょうそうでしょう。
えっダメ?jQueryコードを「wp_head()」の後にきちんと記述していますか?「wp_head()」の中でjQueryライブラリがコールされていることがほとんどです。その後にjQueryコードを記述しないと動作しません。jQueryライブラリが呼ばれてない?よーし「header.php」に「wp_enqueue_script(“jquery”)」を追加だ。
<?php wp_enqueue_script("jquery"); //wp_head()より上にね☆ wp_head(); ?>
まだダメ?jQueryプラグインコードを直接記述ではなくファイル読み込みで使っている?ではそのコードファイルを編集して以下のように全体を囲みましょう。
jQuery(document).ready(function($){ //追加して! //▽元々のコード $(function(){ //なんかコードいっぱい }); //△元々のコード }); //追加して!
禁断のおまじないです。決してオススメはしません。え?それでも動かない?そもそも何言ってるかわからない?もう諦めてこの後の解説をお読み下さい。
2, に当てはまる方はプラグインコードの書き出しを全て先ほどのものに統一した上で複数追加していたjQueryライブラリを削除してみましょう。WordPressで標準出力されているjQueryライブラリでほぼ動きます。出力されていない?よーし「header.php」に「wp_enqueue_script(“jquery”)」を追加だ。
<?php wp_enqueue_script("jquery"); //wp_head()より上にね☆ wp_head(); ?>
プラグインコードによってはバージョンの関係でどうしても動作しないというものもありますが、98%は書き出しのミスが動かない原因です。よそのホスト(Google等)のファイルを読み込んで使っている場合には、諦めましょう。何とかする方法もなくはないですが、ここは一旦諦めてこの後の解説をお読み下さい。
3, のケースはそれほど多くないと思いますが、prototype.jsで「$」のコンフリクト(衝突)が発生した場合jQueryが死にます。というか共倒れです。先ほどの書き出し統一でjQuery側のコンフリクトを回避することはできます。場合によってはprototype.js側でもコンフリクト回避の記述が必要ですが、後はがんばってください。
4, の方、動悸がすごいことになってますよ。大丈夫です。納期はまだです。一旦お水を飲んで呼吸を整えてからこの後の解説をお読み下さい。
解説 – 「$」はただの記号ではない
ワンポイント講座だけでは物足りないという知的好奇心に溢れる方にはここから解説です。
先ほどの症例は全て「$」の扱いによって引き起こされる問題です。jQueryがよく分からずとも「$」を目にされている方は多いと思います。
<script type="text/javascript"> $(function(){ $("#hoge").hover( function(){ $(this).addClass("hogehoge"); }, function(){ $(this).removeClass("hogehoge"); alert('hogehogehogehoge!!!!!!'); } ); }); </script>
文の書き出しによく登場する「$」について少し理解を深めましょう。
それによって皆さんそれぞれの解決方法が見えてくると思います。
解説1 – jQueryとは何なのか
駆け足で学んでいきましょう。
jQueryはスクリプト言語である「javascript」の「ライブラリ」のことです。
ライブラリとは一言で表現すると「拡張機能」です。
「javascriptでは物足りない、もっと多様な機能を実現したい」という有志の手によって開発されました。
ベースの「javascript」があってその中に「jQuery」が存在します。javascriptのライブラリには他にも「Prototype JavaScript framework(Prototype.js)」や「Zepto」等があります。
※これだけではなくライブラリの量はもっと膨大にあります
よくjQueryとjavascriptがごちゃ混ぜにされますがきちんと頭で整理しましょう。
javascript → 仏教
jQuery → 浄土宗(仏教のライブラリ!)
prototype.js → 真言宗(仏教のライブラリ!)
ということです。浄土宗は仏教と言えますが、仏教は浄土宗ではありません。
ただ唐突に宗教の話を持ち出すとよく分からない上に何かを誤解される恐れがあるので、
javascript → ラーメン
jQuery → 博多ラーメン
prototype.js → 和歌山ラーメン
にしておきましょう。身近にぐっと分かりやすくなりましたね。
ラーメンを構成する「麺・スープ・具材」を拡張・変更することで色々なラーメン(ライブラリ)となりますが、しかし「ご飯・卵・醤油」で構成してしまうと卵かけごはんになってしまうのです。後半のは忘れて下さい。
javascript → 日本語(標準語)
jQuery → 関西弁
prototype.js → 東北弁
3つも挙げておけばばっちりでしょう。
段々雑になっていますがまずは雰囲気です。まずは雰囲気。
解説2 – 「$」にはjQueryが詰まっている
jQueryの立ち位置をざっくり理解した後は「$」について。
「$」にはjQueryが詰まっています。jQueryのコードを書こう!と言っても実体は「javascript」のコードを書いているだけということはお気付きでしょうか。
<script type="text/javascript"> $(function(){ $("#hoge").hover( function(){ $(this).addClass("hogehoge"); }, function(){ $(this).removeClass("hogehoge"); alert('hogehogehogehoge!!!!!!'); } ); }); </script>
上のコードを見るとどこにも「jQuery」という記述はありません。これは「javascript」のコードに他ありません。「type=”text/javascript”」と思いっきり書きますよね。しかし、「javascript」には「hover()」なんていう機能(関数)はないのです。普通に書いたらエラーです。では何故動くのか!
解説3 – 「$」はjQueryオブジェクトのことである
読み飛ばさないで下さい!「オブジェクト」やら「プロシージャ」やら「サブルーチン」やらの横文字を目にしただけで拒絶反応を起こさないで下さい!大事なところです!
息を荒げてしまいましたがさて「オブジェクト」という言葉。これは「物体」を意味する横文字です。恐れる必要はありません。ただの物です。物。
それによって「$」で書き始めると「jQuery」の機能を使用可能となる。
その記号「$」には元々特別な意味はなく、単にjQueryの機能を詰め込まれているというだけなのです。しかしここで問題が起こります。
解説4 – 「$」に他のライブラリも詰め込まれることがある
これは大変です。ただの記号「$」に他のライブラリが詰め込まれることもあるのです。有名なところでは本文でも何度か出てきている「prototype.js」です。それによって「$」を使ってjQueryを呼び出しているつもりでもprototype.jsが呼び出されてしまうことがあるのです。
javascript(に限りませんがスクリプト言語一般)は一度エラーが発生するとそこで処理を中断する場合と続行する場合があります。中断された場合には以降のコードが動作しないため、百鬼夜行のエラーが発生します。この記号の衝突を横文字で「コンフリクト」といいます。
さてここで天下のWordPressは考えました。全てのライブラリが分け隔てなく暮らせるよう、滞りなく運用されるためには…そう出来ることは一つ、混乱の元である「$」を封印したのです。しかし事情をよく知らない我々はつい「$」から書き出しをしてしまい、ページ表示に支障をきたしスライダーが突然動かなくなるのです。あっちを直せばこっちが動かぬ状態で茫然自失。結果プラグインコード一つ一つにjQueryライブラリをあてがってみるのです。私もやっていました。
※何故それで「$」が動作する(ことがある)のかは後述
WordPressでは、実行されるjavascriptのコード全体における名前空間・グローバルスコープにおいて「$」を各ライブラリが取り合わないよう調整しています。グローバルスコープは「<script>」タグをまたいでも有効です(これ重要)。
見た目的に独立してそうで実は裏で繋がっているのです。
<script type="text/javascript"> //グローバル空間 var $1 = "hoge!"; //$1という記号に文字列hoge!を代入 $(function(){ //{}で囲まれたローカル空間 var $2 = "hoge!"; //$2という記号に文字列hoge!を代入 }); </script> <script type="text/javascript"> //グローバル空間 - 上の<script>から続いてます alert($1); //記号$1をアラート出力。hoge!が出力される。何故ならグローバルで定義したから alert($2); //記号$2をアラート出力。hoge!は出力されない。何故ならローカルで定義したから </script>
「$(function(){」で書き始めるということは、グローバル空間で「$」に「jQuery」が詰め込まれていることを期待しています。しかし、WordPressが「wp_head()」で出力するjQueryでは「$」に何もセットさせないため、動作しません。
jQueryライブラリをコード手前で直接読み込むと「$(function()」は動作します。何故ならライブラリコード内でグローバル空間の「$」に「jQuery」をセットするためです。しかしこれはWordPressの意図するjavascriptコード空間のルール(「$」の扱い・衝突回避)に反します。ティッシュがないから手で鼻水をかむのと一緒でやむを得ない事情がない限りはやめたほうがいいのです。
結論 – 「$」ではなく「jQuery」で呼び出す
「$」がないとjQueryが呼び出せないじゃないか!いいえ、実は「jQuery」という記号に「jQuery」の機能が詰め込まれているという事実。「$」ではなく「jQuery」。これがミソです。Qのみ大文字です。
「$(function(){」→「jQuery(function($){」
「$(document).ready(function(){」→「jQuery(document).ready(function($){」
1, 最初の「$」を「jQuery」に変更(記号の変更)
2, 更に「function()」の部分を「function($)」に変更(引数の受付)
これによって{}の中(ローカル空間)で「$(記号)」に「jQuery(ライブラリ機能)」が詰め込まれている状態となり、グローバル空間での「コンフリクト」が起きないという寸法。存分に「$」を使い倒すことが出来ます!
<script type="text/javascript"> jQuery(document).ready(function($){ //↓どれだけ$を使ってもいいよゾーン var test = $(".hoge"); $.each(test, function(k, t){ $(this).click(function(){ alert("$を使いたい放題!天国!!"); }); }); $("#hohogege").hover(){ function(){ $("#hoge").html("hogehogehogehogehoge!!!"); }, function(){ $("#hogehoge").attr("alt", "jQuery万歳!!!"); } }); //↑どれだけ$を使ってもいいよゾーン }); //↓ダメ!絶対ダメ!!無理! $(function(){ //ダメゾーン }); //↑ダメ!絶対ダメ!!無理! </script>
ここで勘が良い方はお気付きでしょう。
$を違う記号にしてみる
「jQuery(document).ready(function(hogehoge){」
と書けば、「hogehoge」にjQueryが詰め込まれます。記号はなんだっていいのです。ただ誰も得しません。各人が思い思いに書いているとこれまた混乱の元なので、暗黙的に「$」へ統一されているというだけです。
こうした事情を踏まえると、あなたのサイトでjQueryコードをどう記述しなければならないか見えてくるはずです。
まとめ – 箇条書きで振り返る
1, ライブラリのソースコードを直接読み込むと、各ライブラリは何かしらの記号に自身の機能を詰め込んでコード全体の名前空間(グローバルスコープ)を占領
※それ自体は悪いことではない → どこでも同じ機能を呼び出せるようになるから
2, WordPress側は誰が何のライブラリを使うか分からないので、取り敢えず記号の衝突が起きないよう交通整理(「$」には何もセットされない!)
3, それとは気付かず「$(function(){」とか書く。
4, 実行時、「$ってなんやねん!」とjacascriptコードがエラーを出す
5, エラーが出るとコード実行がその部分で止まりがち。息を呑む展開に。
6, コードが動いてない!バージョンが問題なのか!バージョン違いをぽちっとな → 他のコードが動かなくなる。以下6, のループ
きっちり「jQuery(記号)」で「jQuery(ライブラリ機能)」を呼び出す!
それが一番大事。
補足 – まとめの3, について
何故大抵「$(function(){」で書きだしてしまうのか。
80% → 外部のソースコードをそのまま使っている
20% → そうしたソースコードを見ているうちに「jQueryの書き出しはこうするのか」と思う
関数の書き出しには省略形も存在するため、外部のコードで各書き出しがバラバラなことも余計混乱を招いています。WordPress上での使用前提で書かれているjQueryプラグインコードではその辺を踏まえてちゃんと書き出しが統一されていることもあります。ないこともおっとこれ以上はすいません。
軽量化(文字数削減)を気にしない・複数人が編集するという場合、
個人的には、
◎「jQuery(document).ready(function($){」 分かりやすい
×「jQuery().ready(function($){」 中途半端
○「jQuery(function($){」 許容範囲
一番上が見た目にも何をしているか判断しやすいのでオススメです。それでは。