Hexoのプラグインをカスタマイズする2

04/21

モルモット

JSが動いてないことに気づく

目次

経緯

いつの頃からかYouTubeなどの動画埋め込みの自動再生がされなくなっていた。
恐らくhexo-tag-owlを再インストールしたからだなと。
てことで、もう一度改修する。

要件

まずは改修する要件を明確にする。

  • youtube埋め込みコードの自動生成
  • niconico埋め込みコードの自動生成
  • dailymotion埋め込みコードの自動生成
  • imdbの映画情報タグの自動生成

以上の改修をhexo-tag-owlに対して行う。
そしてさらにyoutube、niconico、dailymotionのエレメントに
jqueryのinviewイベントをトリガーに自動再生を行う。

modified file list

  1. hexo-tag-owl/lib/tag/index.js
  2. hexo-tag-owl/lib/tag/images/imdb.js1
  3. hexo-tag-owl/lib/tag/videos/niconico.js
  4. hexo-tag-owl/lib/tag/videos/nicovideo.js1
  5. hexo-tag-owl/lib/tag/videos/dailymotion.js1
  6. hexo-tag-owl/lib/tag/videos/youtube.js

index.js

index.js

use strict';

/**
* tag list
**/
// tag list
var list = {
videos: {
path: ['.', 'videos'],
tags: ['youtube', 'nicovideo', 'niconico', 'bilibili', 'vimeo', 'tudou', 'youku', 'tencent', 'ted', 'dailymotion']
},
images: {
path: ['.', 'images'],
tags: ['local', 'giphy', 'imdb']
}
};

// selector for recording a lot of videos and images tags
var selector = {};
Object.keys(list).forEach(function (type) {
var path = list[type].path.join('/');
list[type].tags.forEach(function (tag) {
selector[tag] = require(path + '/' + tag);
})
});

module.exports = selector;

imdb.js

imdb.js

'use strict';

const cheerio=require('cheerio-httpcli');

module.exports = (hexo, args) => {
/* search */
let q=args[1];
let title=((q)=>{
let titleArray=q.split(" ");
let searchTitle="";
for(let i=0;i<titleArray.length;i++){
(i!=titleArray.length-1)?searchTitle+=titleArray[i]+'+':searchTitle+=titleArray[i];
}
return searchTitle;
})(q);
let movies=[];
let searchurl='https://www.imdb.com/find';
let searchoptions={
s: 'tt',
ttype: 'ft',
ref_: 'fn_ft',
q: title,
};
const result=cheerio.fetchSync(searchurl, searchoptions);
if(result.error)
return '<div class="owl-media owl-image owl-imdb"><img src="/assets/no-media.png" alt="no media"></div>';
let $=result.$;
$('.findResult').each(async (i, element)=>{
const $image = $(element).find('td a img');
const $title = $(element).find('td.result_text a');
const imdbID = $title.attr('href').match(/title\/(.*)\//)[1];
const movie = {
image: $image.attr('src'),
title: $title.text(),
imdbID : imdbID
};
movies.push(movie);
return false;
});

/* details */
let detailurl='https://www.imdb.com/title/'+movies[0].imdbID+'/';
let detailoptions={
ref_:'fn_al_tt_1',
};
const result2=cheerio.fetchSync(detailurl, detailoptions);
if(result2.error)
return '<div class="owl-media owl-image owl-imdb"><img src="/assets/no-media.png" alt="no media"></div>';
$=result2.$;
var articleChildren = $('.subtext').children()
var movieDetails = {
title : $('.title_wrapper h1').text(),
year: $('#titleYear a').text(),
rating : $('.ratingValue strong span').text(),
votes : $('.imdbRating a span').text(),
time : $('.subtext time').text().trim(),
poster : $('.poster a img').attr('src'),
release : $(articleChildren[7]).text().trim(),
story : $('.article .canwrap p span').text().trim(),
writtenBy : $('.article .canwrap em a').text()
}
return '<div class="owl-media owl-image owl-imdb"><img src="'+movieDetails.poster+'" alt="'+movieDetails.title+'"><div class="imdb-staff"><ul><li>Title: '+movieDetails.title+'</li><li>Release Date: '+movieDetails.release+'</li></ul></div></div>';
}

niconico.js

niconico.js

'use strict';

var config = require('./config');
// niconico
module.exports = function (hexo, args) {
var id = args[0],
type = args[1] || 'thumb',
res = '';
if ('thumb' === type) {
// thumb
res += '<div class="owl-media owl-video owl-niconico niconico-thumb"><iframe src="//ext.nicovideo.jp/thumb/' + id + '" scrolling="no" ' + config.iframe + '></iframe></div>';
}
else {
// watch
res += '<div class="niconico-video owl-media owl-video owl-niconico niconico-watch" data-video-id="'+id+'"><div class="movie-wrap" data-video-id="'+id+'"></div></div>';
}
return res;
}

nicovideos.js

これはタグ名をすぐ忘れるので作っただけ。

{% owl niconico sm9999999 watch %}
{% owl nicovideo sm9999999 watch %}

どっちの書き方が合っているかうろ覚えだったので、だったらどっちも書けるようにしただけ。
niconico.jsをコピーしただけ。

dailymotion.js

dailymotion.js

'use strict';

var config = require('./config');
// dailymotion
module.exports = function (hexo, args) {
var id = args[0];
return '<div class="owl-media owl-video owl-dailymotion"><div class="dmplayer" dailyid="'+id+'" playoption="off"></div></div>';
}

youtube.js

youtube.js

'use strict';

var config = require('./config');
// youtube 9:16
module.exports = function (hexo, args) {
var id = args[0];
return '<div class="owl-media owl-video owl-youtube"><div class="movie-wrap"><div id="yt__'+id+'" class="youtube-video" width="854" height="480" data-video-id="'+id+'"></div></div></div>';
}

ここまででプラグインの改修は終わり。
次はView側を手をつける。

CSS

hexoはmain.cssを使っているので見た目を変えていく。
やったことはレスポンシブ対応のため

<div class="owl-video">
<div class="movie-wrap">
<iframe/>
</div>
</div>

こんな構造としてiframeは常に100%の大きさで、movie-wrapクラスのdivエレメントでは大きさを考慮してパディングを確保、親のdivエレメントで最大の大きさを調整って感じ。
やったことはこんな感じ。

main.css

@media (min-width:1099px){
.owl-video {
max-width: 800px;
margin: 0 auto;
}
}
@media (max-width:1099px) {
.owl-video {
max-width: 600px;
margin: 0 auto;
}
}

.movie-wrap {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
}
.movie-wrap iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

JavaScript

先のタグの構造を実現するために以下を行っている。
YouTubeはjquery.youtube-inview-autoplay.jsで実現しているので、ここではniconicoとDailymotionだけ実現している。

main.js

$(document).ready(function(){
$("div.niconico-video div.movie-wrap").each((i, _div)=>{
$.when(
$('<iframe>').attr({
src: nicosrc+'/watch/' + $(_div).attr("data-video-id") + '?jsapi=1&playerId=' + i,
id: 'nicovideoPlayer-' + i,
frameborder: 0,
allowfullscreen: '',
width: '100%',
height: '100%'
}).appendTo($(_div))
).done((obj)=>{
nicoPlayer.push(obj[0]);
$(obj[0]).on('inview', function(event, isInView) {
if (isInView) {
// element is now visible in the viewport
nicoPostMessage(event.target.id,
{
sourceConnectorType: 1,
eventName: 'play'
});
$("#nowplaying-img>img").attr('src', obj[0].thumbnail_url);
$("#nowplaying-product-title").text(obj[0].title);
$("#nowplaying-product-author").text('');
} else {
// element has gone out of viewport
nicoPostMessage(event.target.id,
{
sourceConnectorType: 1,
eventName: 'pause'
});
$('#nowplaying-product-title').text(nowPlayingTitle);
$('#nowplaying-img>img').attr('src',nowPlayingImageUrl);
$('#nowplaying-product-author').text(nowPlayingAuthor);
}
});
}).fail();
});

window.addEventListener('message', (e) => {
if (e.origin !== nicosrc) return;
if (nicoPlay === undefined) nicoPlay=0;
if (e.data.playerId === nicoPlay) {
const { data } = e.data;
switch (e.data.eventName) {
case 'playerMetadataChange': {
nicoPlayerMetadataChange(data);
break;
}
case 'playerStatusChange': {
nicoPlayerStatusChange(data);
break;
}
case 'loadComplete': {
nicoRenderInfoTable(data.videoInfo);
break;
}
default:
console.log(e.data);
}
nicoPlaying = Object.assign({}, nicoPlaying, data);
}
});

$('.dmplayer').each((i, _div)=>{
$.when(
$(_div).wrap(
$('<div>').attr({
class: 'movie-wrap'
})
)
).done((obj)=>{
$(_div).attr('id','dmplayer-'+i);
let videoid=$(_div).attr('dailyid');
let isautoplay=($(_div).attr('playoption')=="on")?true:false;
let player=DM.player(_div, {
video: videoid,
width: "100%",
height: "100%",
params: {
autoplay: isautoplay,
mute: false
}
});
player.load();
dmPlayer.push(player);
$('#dmplayer-'+i).on('inview', (event, isInView)=>{
if (isInView) {
// element is now visible in the viewport
player.play();
$('#nowplaying-product-title').text(player.video.title);
$('#nowplaying-img>img').attr('src',player.video.thumbnail_url);
$('#nowplaying-product-author').text('');
} else {
// element has gone out of viewport
player.pause();
$('#nowplaying-product-title').text(nowPlayingTitle);
$('#nowplaying-img>img').attr('src',nowPlayingImageUrl);
$('#nowplaying-product-author').text(nowPlayingAuthor);
}
});
$('#dmplayer-'+i).attr('height','400');
}).fail();
});
});

では、これでやってみる。

Leeeettttt’s do it again

$ cd $HEXO_HOME
$ cd node_modules/hexo-tag-owl
$ npm i cheerio-httpcli --save
$ cd ../..
$ rm db.json
$ hexo g

$HEXO_HOMEは適宜読み替えていただきたい。
これでやりたいことはできた。
うれしい。


  1. 1.新規作成

コメント: