WP Social Bookmarking Lightとprototype.jsについて

WP Social Bookmarking Lightというプラグインを切っ掛けに、javascriptに関して掘り下げてみる機会を得たので、書き残しておこうと思います。

現在このサイトで動いているWordPressはversion 3.8.1で、現行の最新バージョンです。加えて、同時リリースされたTwenty Fourteenに模様替えしました。

planetleaf-com_wordpress381

さて、早速WP Social Bookmarking Lightを入れてみたところ設定画面が以下のように…、


wpsbl-syntax-error

 

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);
    }
}

はい、この通り

wpsbl-fix-problem

因みに無理やり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);
  }

結果はこの通り、
wpsbl-debug-on-ie-for-valueserver01

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なんでサーバーは関係ありませんが
wpsbl-debug-on-ie-for-valueserver02

そして、この現象を引き起こすプラグインを特定。

当サイトで広告を管理している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のディレクトリに上がっている分に関しては中の人によろしくお願いしますという感じです。

WordPress

Posted by redchat