/* | |
TwineTubular | |
A twine macro for making YouTube powered background images | |
Hacked mercilessly into twine by Jonathan Prior | |
http://jonathanprior.com | |
HOW TO USE | |
<<playvideo RWgg5-kUSho 0>> | |
argument 1 is the ID of the YT video | |
argument 2 is the time you want to start the video at in seconds | |
argument 3 should be "loop" if you want the video to loop | |
argument 4 should be "sound" if you want sound from the video | |
so for a video that skips ahead to 20 seconds and loops: | |
<<playvideo RWgg5-kUSho 20 loop>> | |
for the same video as above, but with sound: | |
<<playvideo RWgg5-kUSho 20 loop sound>> | |
for the same video as above, with sound but not looping: | |
<<playvideo RWgg5-kUSho 20 noloop sound>> | |
The video plays automatically throughout the passage you include it in. | |
To stop the video, in the next passage, use the <<stopvideo>> macro | |
*/ | |
window._tubular = undefined; | |
window.jquery_url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/'; | |
var s = document.createElement('script'); | |
s.src = jquery_url + 'jquery.min.js'; | |
s.onload = function f(){ | |
if (jQuery) { | |
jQuery.noConflict(); | |
} | |
} | |
document.getElementsByTagName("head")[0].appendChild(s); | |
if (!document.getElementById("ytjs")) { | |
var tag = document.createElement('script'); | |
tag.src = "https://www.youtube.com/iframe_api"; | |
tag.id = "ytjs"; | |
var firstScriptTag = document.getElementsByTagName('script')[0]; | |
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); | |
} else { | |
try { | |
window.onYouTubeIframeAPIReady(); | |
} catch(e) { | |
void(0); | |
} | |
} | |
macros["playvideo"]={ | |
handler: function(place, macroName, params, parser) { | |
/* jQuery tubular plugin | |
|* by Sean McCambridge | |
|* http://www.seanmccambridge.com/tubular | |
|* version: 1.0 | |
|* updated: October 1, 2012 | |
|* since 2010 | |
|* licensed under the MIT License | |
|* Enjoy. | |
|* | |
|* Thanks, | |
|* Sean */ | |
;(function ($, window) { | |
// test for feature support and return if failure | |
// defaults | |
var defaults = { | |
ratio: 16/9, // usually either 4/3 or 16/9 -- tweak as needed | |
videoId: 'ZCAnLxRvNNc', // toy robot in space is a good default, no? | |
mute: true, | |
repeat: true, | |
width: $(window).width(), | |
wrapperZIndex: 99, | |
playButtonClass: 'tubular-play', | |
pauseButtonClass: 'tubular-pause', | |
muteButtonClass: 'tubular-mute', | |
volumeUpClass: 'tubular-volume-up', | |
volumeDownClass: 'tubular-volume-down', | |
increaseVolumeBy: 10, | |
start: 0 | |
}; | |
// methods | |
var tubular = function(node, options) { // should be called on the wrapper div | |
var options = $.extend({}, defaults, options), | |
$body = $('body') // cache body node | |
$node = $(node); // cache wrapper node | |
// build container | |
var tubularContainer = '<div id="tubular-container" style="overflow: hidden; position: fixed; z-index: -99; width: 100%; height: 100%; top: 0; left: 0"><div id="tubular-player" style="position: fixed"></div></div><div id="tubular-shield" style="width: 100%; height: 100%; z-index: -97; position: fixed; left: 0; top: 0;"></div>'; | |
// set up css prereq's, inject tubular container and set up wrapper defaults | |
//$('html,body').css({'width': '100%', 'height': '100%'}); | |
$body.prepend(tubularContainer); | |
$node.css({position: 'relative', 'z-index': options.wrapperZIndex}); | |
// set up iframe player, use global scope so YT api can talk | |
window.player; | |
window.onYouTubeIframeAPIReady = function() { | |
player = new YT.Player('tubular-player', { | |
width: options.width, | |
height: Math.ceil(options.width / options.ratio), | |
videoId: options.videoId, | |
playerVars: { | |
controls: 0, | |
showinfo: 0, | |
modestbranding: 1, | |
rel: 0, | |
wmode: 'transparent' | |
}, | |
events: { | |
'onReady': onPlayerReady, | |
'onStateChange': onPlayerStateChange | |
} | |
}); | |
} | |
window.onPlayerReady = function(e) { | |
resize(); | |
if (options.mute) e.target.mute(); | |
e.target.seekTo(options.start); | |
e.target.playVideo(); | |
} | |
window.onPlayerStateChange = function(state) { | |
if (state.data === 0 && options.repeat) { // video ended and repeat option is set true | |
player.seekTo(options.start); // restart | |
} | |
} | |
// resize handler updates width, height and offset of player after resize/init | |
var resize = function() { | |
var width = $(window).width(), | |
pWidth, // player width, to be defined | |
height = $(window).height(), | |
pHeight, // player height, tbd | |
$tubularPlayer = $('#tubular-player'); | |
// when screen aspect ratio differs from video, video must center and underlay one dimension | |
if (width / options.ratio < height) { // if new video height < window height (gap underneath) | |
pWidth = Math.ceil(height * options.ratio); // get new player width | |
$tubularPlayer.width(pWidth).height(height).css({left: (width - pWidth) / 2, top: 0}); // player width is greater, offset left; reset top | |
} else { // new video width < window width (gap to right) | |
pHeight = Math.ceil(width / options.ratio); // get new player height | |
$tubularPlayer.width(width).height(pHeight).css({left: 0, top: (height - pHeight) / 2}); // player height is greater, offset top; reset left | |
} | |
} | |
// events | |
$(window).on('resize.tubular', function() { | |
resize(); | |
}) | |
$('body').on('click','.' + options.playButtonClass, function(e) { // play button | |
e.preventDefault(); | |
player.playVideo(); | |
}).on('click', '.' + options.pauseButtonClass, function(e) { // pause button | |
e.preventDefault(); | |
player.pauseVideo(); | |
}).on('click', '.' + options.muteButtonClass, function(e) { // mute button | |
e.preventDefault(); | |
(player.isMuted()) ? player.unMute() : player.mute(); | |
}).on('click', '.' + options.volumeDownClass, function(e) { // volume down button | |
e.preventDefault(); | |
var currentVolume = player.getVolume(); | |
if (currentVolume < options.increaseVolumeBy) currentVolume = options.increaseVolumeBy; | |
player.setVolume(currentVolume - options.increaseVolumeBy); | |
}).on('click', '.' + options.volumeUpClass, function(e) { // volume up button | |
e.preventDefault(); | |
if (player.isMuted()) player.unMute(); // if mute is on, unmute | |
var currentVolume = player.getVolume(); | |
if (currentVolume > 100 - options.increaseVolumeBy) currentVolume = 100 - options.increaseVolumeBy; | |
player.setVolume(currentVolume + options.increaseVolumeBy); | |
}); | |
if (!document.getElementById("ytjs") == false) { | |
window.onYouTubeIframeAPIReady(); | |
} | |
} | |
// load yt iframe js api | |
// create plugin | |
window._tubular = window._tubular || tubular; | |
})(jQuery, window); | |
window._tubular(jQuery("body"), {videoId: params[0], start: params[1], repeat: (params[2] == "loop"), mute: (params[3] !== "sound")}); | |
} | |
} | |
macros["stopvideo"] = { | |
handler: function(place, macroName, params, parser) { | |
jQuery("#tubular-container").remove(); | |
jQuery("#tubular-shield").remove(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment