ドグサレ初心者のへっぽこビッグウェーブ

地球の底辺にいるゴミがプログラミングとか音楽とかを語るクソブログ

力技でyoutube動画だけじゃなくてニコニコ動画もエンベッドさせてみる

テストデータをいろいろ入れてみていると、youtubeに情報が存在しない場合が多々あり。

そしてそんなときに限ってニコニコ動画ではあったりして。

ニコニコ動画も貼り付けたーい!!


だがしかし。absg.hatenablog.com
ニコ動はURLだけでなくJavascript埋め込まないとダメっぽい空気。

うーんうーんと悩んでみた結果、
「動画情報のレコードにニコ動外部プレイヤーのURLまるっと格納すればいいんじゃね?」という結論に至る。

なので、 anime_detail.ed(またはop)_movie のレコードのタイプを、

の2通りが入ってくると想定して場合分け表示すればいいのではなかろうか。

これをマッチングさせて処理を挟むことにする。

まるっと外部プレイヤーURLを格納して呼び出す

ためしに表示部分を正規表現で条件分岐させてみる。
以下、調べたとことか引っかかったところ。注意すべし。

  • パターンマッチングの基本は「正規表現 =~ 文字列」
    • 正規表現は "/hoge/"とスラッシュで囲む。
    • "^"で行頭からのマッチングパターンにできる
  • 複数条件分岐の場合は、「else if」じゃない!「elsif」です(参照) エルスィフ。
  • ニコ動の場合はhtmlタグを出力したいので、"<%== %>"と=を二つ重ねてエスケープしないで出力する
    • 単純に"<%= %>"で囲むとエスケープ処理されてしまい文字列が出力されてしまう
- <div class="youtube-container">
-   <iframe id="player" type="text/html" width="640" height="390"
-           src="<%= anime_detail.ed_movie %>"
-           frameborder="0"></iframe>
- </div>

+ <% if /^<script/ =~ anime_detail.ed_movie %>     //ニコ動の場合
+     <%== anime_detail.ed_movie %>     //エスケープせずに出力
+ <% elsif /www.youtube.com/ =~ anime_detail.ed_movie %>     //youtubeの場合はこれまでと同じ
+     <div class="youtube-container">
+       <iframe id="player" type="text/html" width="640" height="390"
+               src="<%= anime_detail.ed_movie %>"
+               frameborder="0"></iframe>
+     </div>
+ <% end %>

やってみたらできました。わーい。いいぞいいぞー。

と、思ったら。

テストで別の位置に直貼りしたニコ動urlがあったから動いてたぽい。ちくしょう。
ページ直打ちだったら表示されるけど、別ページからの遷移だと表示されず。
scriptタグは記述されてるけど、その後に追記されるはずのエンベッドが書かれない。

scriptタグはあるけど動いてないぽい原因はdocument.writeだそうです

なんだかnoscript以降がバニシュしてしまうもよう。
www.htmq.com
バニシュするのが通常のご様子。あらはずかしい。


mementoo.info

ニコニコ動画の外部プレイヤーはページのはじめの読み込みのときにしか表示されず、javascriptで読み込みの後から追加で表示させようと思ってもうまくいきません。これは実際に中身を見てみればわかることですが、ソース内で「document.write」を使用して表示させているからです。

だそうです。くぅー。

こうなると、動画URLは以下の2通りで考えてもよさそう

というわけでこのサイトを参考に、jQueryを使って要素内に直接書き出し。

<% if /^<script/ =~ anime_detail.ed_movie %>
    <div id="nico_player">
    </div>
    <p><script type="text/javascript">
       $(function(){
           document._write = document.write;
           document.write = function(msg) {
               // id名nico_playerに表示させる
               $("#nico_player").html(msg);
               //document.writeを元に戻す
               document.write = document._write;
           }
           var id = "sm00000000";
           var src = "http://ext.nicovideo.jp/thumb_watch/" + id;
           var dst = $("<scr"+"ipt>");  //タグと間違われないようにsplit
           dst.attr("type", "text/javascript");
           dst.attr("src", src);
           //追加
           $("body").append(dst);
       });
    </script></p>
<% elsif /www.youtube.com/ =~ anime_detail.ed_movie %>
    <div class="youtube-container">
       <iframe id="player" type="text/html" width="640" height="390"
                 src="<%= anime_detail.ed_movie %>"
                 frameborder="0"></iframe>
    </div>
<% end %>

とりあえずこれで画像表示できるようになりマスタング

パターンマッチングをもう一度整理

ただこのままだと条件分岐おかしいし手打ちで動画表示させてるので、anime_detail.ed(またはop)_movie に格納するURLのパターンをもう一度整理。
URLはわざわざ外部貼り付けURLとか出さずにアドレスバーから直接コピペすることができるようになって楽かも。

[anime_detail.ed(またはop)_movieに格納するURL]

[パターンマッチング]

[引用パラメータ]

  • youtube型:hogehoge(v=以降部分)
  • niconico型:hogehoge(watch/以降部分)


マッチング場所と引用パラメータ別々にする必要なくない?と思うのでやりなおして。

[ マッチング&引用パラメータ ]

  • youtube型:?v=でマッチさせて、以降のid部分を抽出
  • niconico型:/watch/でマッチさせて、以降のid部分を抽出

これに合わせて条件分岐とniconico型の引用パラメータ、youtube型のsrcパラメータなどなどを修正。

まとめ

最終的に作成した、サイトURLからニコニコ動画 or youtube動画をエンベッド埋め込みする方法。

[anime_detail.op_movieに格納するURL]

[ .html.erb ] ※cssは省略

<% @anime_details.each do |anime_detail| %>
    <% if anime_detail.op_artist? %>
        <br><p>artist:<span class="h3"> <%= anime_detail.op_artist %></span></p>
        <p>title:<span class="h3"> <%= anime_detail.op_title %></span></p>
        <% if /\/watch\/([^&]+)/ =~ anime_detail.op_movie  #niconico %>
            <div id="nico_player">
            </div>
            <p><script type="text/javascript">
                $(function(){
                    document._write = document.write;
                    document.write = function(msg) {
                        // id名nico_playerに表示させる
                        $("#nico_player").html(msg);
                        //document.writeを元に戻す
                        document.write = document._write;
                    }
                    var src = "http://ext.nicovideo.jp/thumb_watch/<%= $1 %>";
                    var dst = $("<scr"+"ipt>");  //タグと間違われないようにsplit
                    dst.attr("type", "text/javascript");
                    dst.attr("src", src);
                    //追加
                    $("body").append(dst);
                });
            </script></p>
        <% elsif /\?v=([^&]+)/ =~ anime_detail.op_movie  #youtube %>
            <div class="youtube-container">
                <iframe id="player" type="text/html" width="640" height="390" src="https://www.youtube.com/embed/<%= $1 %>" frameborder="0"></iframe>
            </div>
        <% end %>
    <% end %>
<% end %>

スクリプト部分は外部ファイルで置いた方が収まりがいいのだろうけど、とりあえずはこれで。


あとはURLをどうやって楽にテーブルに格納するかだなぁ。ぬーん。


TODO:

  • フォームの例外処理エラーがおかしい
  • トップからtitle/showへの遷移、2回目以降がなぜかおかしな位置(ページ中段)に遷移するので修正
  • detailページのレイアウト直すのとdetail -> title/showの動線を置く
  • 動画URLもっと楽に入れたい