WP Social Bookmarking Lightとprototype.jsについて
WP Social Bookmarking Lightというプラグインを切っ掛けに、javascriptに関して掘り下げてみる機会を得たので、書き残しておこうと思います。
現在このサイトで動いているWordPressはversion 3.8.1で、現行の最新バージョンです。加えて、同時リリースされたTwenty Fourteenに模様替えしました。
さて、早速WP Social Bookmarking Lightを入れてみたところ設定画面が以下のように…、
FireFoxでデバッグしてみたところシンタックスエラーが出てます。恐らくjQuery周りなのですが、根本の原因は別にあると思いトレースしてみると…。
wp-social-bookmarking-light/modules/admin.php
jQuery("#wsbl_draggable, #wsbl_sortable").disableSelection(); wsbl_update_sortable(); wsbl_update_services(true); jQuery("#tabs").tabs(); }); //]]> </script>
wsbl_update-servicesから処理が帰ってこれないようです。この先で最終的にシンタックスエラーが出ているようです。
そんな訳で該当ファンクションへ
function wsbl_update_services(is_simply) { var vals = ""; var service = jQuery("#wsbl_sortable .wsbl_txt_draggable"); service.each(function(){ vals += vals == "" ? "" : ","; vals += jQuery(this).text(); }); jQuery("#services_id").val(vals); is_simply = is_simply || false; var services = ['mixi', 'twitter', 'hatena_button', 'facebook', 'gree', 'evernote', 'tumblr', 'atode', 'google_plus_one', 'line', 'pocket']; for(var i in services){ wsbl_tab_toggle(services[i], is_simply); } }
見つけました。
ループによる配列の走査ですが、for inはオブジェクトに対応するプロパティを走査するための物で、これでは条件次第で不定値を拾ってしまいます。
よって、普通に配列のlengthプロパティを取得して、その数だけループを回します。
function wsbl_update_services(is_simply) { var vals = ""; var service = jQuery("#wsbl_sortable .wsbl_txt_draggable"); service.each(function(){ vals += vals == "" ? "" : ","; vals += jQuery(this).text(); }); jQuery("#services_id").val(vals); is_simply = is_simply || false; var services = ['mixi', 'twitter', 'hatena_button', 'facebook', 'gree', 'evernote', 'tumblr', 'atode', 'google_plus_one', 'line', 'pocket']; for (var i = 0; i < services.length; i++){ wsbl_tab_toggle(services[i], is_simply); } }
はい、この通り
因みに無理やりfor inで書いてしまうとこんな感じに
var services = { mix:'mixi', twi:'twitter', hat:'hatena_button', fac:'facebook', gre:'gree', eve:'evernote', tum:'tumblr', atd:'atode', gpo:'google_plus_one', lin:'line', pct:'pocket'}; for(var i in services){ wsbl_tab_toggle(services[i], is_simply); }
forEachというメソッドがあって、こうも書けるようです。
var services = ['mixi', 'twitter', 'hatena_button', 'facebook', 'gree', 'evernote', 'tumblr', 'atode', 'google_plus_one', 'line', 'pocket']; services.forEach(function(v){ wsbl_tab_toggle(v, is_simply); });
さて起こったエラーについてですが、条件次第という事でもう少し掘り下げてみる事にします。
定義した文字列群を超える添え字というか、プロパティを参照してエラーが起きている訳ですが、試しに定義したserversという配列変数のタイプとプロパティ一覧を見てみることにしました。なお、実行はシェアの高さからIE 11で行う事とします。
var services = ['mixi', 'twitter', 'hatena_button', 'facebook', 'gree', 'evernote', 'tumblr', 'atode', 'google_plus_one', 'line', 'pocket']; var propertys = typeof services + "\n"; for(var i in services){ propertys += "[" + i + "],"; } alert(propertys); for(var i in services){ wsbl_tab_toggle(services[i], is_simply); }
javascriptには詳しくないのですが、基底クラスがオーバーライドされていると考えるべきでしょうか…、
0 1 2 3 4 5 6 7 8 9 10 each eachSlice all any collect detect findAll select grep include member inGroupsOf inject invoke max min partition pluck reject sortBy toArray entries zip size inspect _reverse _each clear first last compact flatten without uniq intersect clone
このキーワード群を元に検索してみると、Prototype JavaScript Frameworkという物が存在して、WordPressにJQuery等と共に用意されているデフォルトライブラリだという事が分かりました。
因みに同サーバー上のプレーンな状態で同じ配列を定義するとこうなります。まぁ…javascriptなんでサーバーは関係ありませんが
そして、この現象を引き起こすプラグインを特定。
当サイトで広告を管理しているAdSense Managerがこの現象に関する何かを行っているらしのでソースコードを追ってみると以下の呼び出しを発見。
class adsensem_admin { function init_admin() { global $_adsensem, $wp_version; add_action('admin_head', array('adsensem_admin','add_header_script')); add_action('admin_footer', array('adsensem_admin','admin_callback_editor')); wp_enqueue_script('prototype'); wp_enqueue_script('postbox');
マークしてある部分の呼び出しで adminのページにprototype.jsが挿入されて、WP Social Bookmarking Lightの設定ページでもprototypeが拡張された事が原因のようです。よって、これはAdSense Managerに限らず、他のプラグインでも起こりえます。
この結論にたどり着くにあたり、prototypeの挿入に関してかちびと.netさんの記事、配列走査に関してCreさんの記事を参考にさせていただきました。予備知識が乏しい中、こういった記事は非常に助けになりました。
そんな訳でWPのディレクトリに上がっている分に関しては中の人によろしくお願いしますという感じです。
ディスカッション
コメント一覧
まだ、コメントがありません