I have a repeater that out puts panels for a slide show plugin, slick.js. So far, things are working as planned.
The user, when creating the custom page, enters in copy, then either and image, video from the media library, or a link to you tube.
What i'm trying to do is write the JS function that will fire when the user clicks play on the youtube video.
The webpart injects the youtube video via the iFrame method.
Here's my transformation:
<section class="slide">
<div class="copy">
<%# Eval("SlideContent") %>
</div>
<asp:PlaceHolder runat='server' id='slideImage' visible='<%# IfEmpty( Eval("SlideImage"), false, true ) %>'>
<div class="img">
<img class="img-responsive" src="<%# Eval(" SlideImage ") %>" alt="<%# Eval(" SlideContent ") %>">
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='slideVideo' visible='<%# IfEmpty( Eval("SlideVideo"), false, true ) %>'>
<div class='videoHolder html5'>
<video id='video' class='html5Video' controls>
<source src='<%# Eval("SlideVideo") %>'>
</video>
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='youTubeVideo' visible='<%# IfEmpty( Eval("YouTubeVideo"), false, true ) %>'>
<%# Register Src="~/CMSWebParts/Media/YouTubeVideo.ascx" TagName="YoutubeVideo" TagPrefix="webPart" %>
<div class='videoHolder yt'>
<webPart:YoutubeVideo runat="server" id="YouTubeVideoWebpart" CssClass="ytVideo" VideoURL='<%# ResolveMacros(Eval("YouTubeVideo").ToString())%>' FullScreen='true' />
</div>
</asp:PlaceHolder>
</section>
And here is my JS (this also includes the code to pause videos if the slider changes)
$(function () {
'use strict';
var $slider = $('.slider'),
$slickJS = '/kffIntranet/ui/bower_components/slick-carousel/slick/slick.min.js';
// we check for a slider on the page
if ($slider.length !== 0) {
// if there is a slider, we load the slick.js plugin
$.getScript($slickJS, function () {
// init the slider
$slider.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
slidesToScroll: 1,
fade: false,
lazyLoad: 'ondemand',
adaptiveHeight: true,
autoplay: true,
autoplaySpeed: 5000,
responsive: [{
breakpoint: 1024,
settings: {}
}, {
breakpoint: 600,
settings: {}
}, {
breakpoint: 480,
settings: {
arrows: false
}
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});
});
//
// video control. If a slide has video, we need to pause
//bind our event here, it gets the current slide and pauses the video before each slide changes.
$slider.on('beforeChange', function (event, slick) {
var currentSlide, player, command, videoType;
//find the current slide element and decide which player API we need to use.
currentSlide = $(slick.$slider).find('.slick-current');
//determine which type of slide this by looking for the video holder than getting the video type class
if (currentSlide.find('.videoHolder').length) {
videoType = $('.videoHolder', currentSlide).attr('class').split(' ')[1];
//get the iframe inside this slide.
player = currentSlide.find('iframe').get(0);
}
// pause videos
if (videoType === 'yt') {
command = {
'event': 'command',
'func': 'pauseVideo'
};
player.contentWindow.postMessage(JSON.stringify(command), '*');
} else if (videoType === 'html5') {
document.getElementById('video').pause();
}
});
// pause slider if a video is playing
// html 5 video click
$('.html5Video').on('click', function () {
var $video = $(this).get(0);
// control pause play state of video
if ($video.paused) {
$video.play();
} else {
$video.pause();
}
// call slide pause function
pauseSlide();
});
// youtube play
$('.ytVideo iframe').on('click', function () {
// call slide pause function
pauseSlide();
});
}
// puse slider function
function pauseSlide() {
$slider.slick('slickPause');
console.log('pause');
}
});
So i've created a function pauseSlide that will pause the slider, but i'm struggling with capturing the youtube play click.
Check this answer out. It suggests using the YouTube iframe API.
<!DOCTYPE html> <html> <head> <script src="https://www.youtube.com/iframe_api"></script> </head> <body> <div id='vidWrapper'> <!-- The <iframe> (and video player) will replace this <div> tag. --> <div id="ytplayer"></div> </div> <script> var player; function onYouTubeIframeAPIReady() { player = new YT.Player('ytplayer', { height: '390', width: '640', videoId: 'M7lc1UVf-VE', events: { 'onStateChange': function(event) { if (event.data == YT.PlayerState.PLAYING) { pauseAudio(); } } } }); } function pauseAudio() { ... } </script> </body> </html>
Ok, so i took a step back in this. The transformation now looks for a YouTube ID and then i have a jQuery plugin take over.
So the slider auto playes, and if a video (either youtube, or mp4) is started, the slider stops. Also, if either of the slider direction arrows, or one of the pips are clicked, the video will pause.
I still need to refactor and add some logic, but it's working.
Here's the updated transformation:
<section class="slide">
<div class="copy">
<%# Eval("SlideContent") %>
</div>
<asp:PlaceHolder runat='server' id='slideImage' visible='<%# IfEmpty( Eval("SlideImage"), false, true ) %>'>
<div class="img">
<img class="img-responsive" src="<%# Eval(" SlideImage ") %>" alt="<%# Eval(" SlideContent ") %>">
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='slideVideo' visible='<%# IfEmpty( Eval("SlideVideo"), false, true ) %>'>
<div class='videoHolder html5'>
<video id='video' class='html5Video' controls>
<source src='<%# Eval("SlideVideo") %>'>
</video>
</div>
</asp:PlaceHolder>
<asp:PlaceHolder runat='server' id='youTubeVideoID' visible='<%# IfEmpty( Eval("YouTubeVideoID"), false, true ) %>'>
<div class='videoHolder yt' data-vID='<%# Eval("YouTubeVideoID") %>'>
<div class="vh"></div>
</div>
</asp:PlaceHolder>
</section>
my video.js file
$(function () {
'use strict';
var vHolder = $('.videoHolder'),
vtPlugin = '/kffIntranet/ui/scripts/plugins/tubePlayer/jQuery.tubeplayer.min.js',
vID;
// check for a youtube video, and if there is one, load the youtube pluging
if ($('.yt').length) {
// load plugin
$.getScript(vtPlugin, function () {
// once plugin is loaded, loop through each YT and call the plugin
$('.yt').each(function (i, v) {
var $this = $(this);
vID = $this.attr('data-vid');
$('.vh', $this).tubeplayer({
initialVideo: vID,
onPlayerPlaying: function () {
$('.slider').slick('slickPause');
}
});
});
});
} else if ($('.html5').length) {
$('.html5 .html5video').bind('pause', function () {
$('.slider').slick('slickPause');
});
}
});
and my slider js file
$(function () {
'use strict';
var $slider = $('.slider'),
$slickJS = '/kffIntranet/ui/bower_components/slick-carousel/slick/slick.min.js',
videoType;
// we check for a slider on the page
if ($slider.length !== 0) {
// if there is a slider, we load the slick.js plugin
$.getScript($slickJS, function () {
// init the slider
$slider.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
slidesToScroll: 1,
fade: false,
lazyLoad: 'ondemand',
adaptiveHeight: true,
autoplay: true,
autoplaySpeed: 5000,
responsive: [{
breakpoint: 1024,
settings: {}
}, {
breakpoint: 600,
settings: {}
}, {
breakpoint: 480,
settings: {
arrows: false
}
}
// You can unslick at a given breakpoint now by adding:
// settings: "unslick"
// instead of a settings object
]
});
});
// on slide change
$slider.on('beforeChange', function (event, slick) {
var currentSlide;
//find the current slide element and decide which player API we need to use.
currentSlide = $(slick.$slider).find('.slick-current');
//determine which type of slide this by looking for the video holder than getting the video type class
if (currentSlide.find('.videoHolder').length) {
videoType = $('.videoHolder', currentSlide).attr('class').split(' ')[1];
}
// pause videos
if (videoType === 'html5') {
document.getElementById('video').pause();
} else if (videoType === 'yt') {
$('.vh', currentSlide).tubeplayer('pause');
}
});
}
});
Related
I'm using vue-typed-js library to trigger typing animation with nuxt.js.It works perfectly on load, but I want to trigger this animation when user scrolls to that particular section. Basically controlling typing animation so they work only when element is in view. See this example in wordpress https://www.ennostudio.com,
here is my code for second section of the website.
added v-observe-visibility which works as well for adding classes for elements in view. am also using i18n for string translations.
<template>
<section>
<b-container class="enno_clients section">
<b-row>
<b-col cols="6">
<h6>02 / {{ $t('home.clients.subheading') }}</h6>
<vue-typed-js
v-observe-visibility="{ callback: isViewableNow, once: true }"
:class="{ 'visible': showAnimation, 'invisible': !showAnimation }"
:typeSpeed="30" :showCursor="false" :strings="[ $t('home.clients.heading') ]" >
<h2 class="main_hero_heading typing"></h2>
</vue-typed-js>
</b-col>
<b-col cols="6" >
asd
</b-col>
</b-row>
</b-container>
</section>
</template>
<style scoped>
.visible { visibility: visible; opacity:1; }
.invisible { visibility: hidden; opacity:0; }
</style>
<script>
export default {
name: 'Clients',
data() {
return {
show_hero_content: true,
showAnimation: false,
VueTypedJs: ''
}
},
methods:{
isViewableNow(isVisible, entry) {
this.showAnimation = isVisible;
console.log('isViewableNow');
}
},
mounted() {
this.show_hero_content = false;
},
}
</script>
I'm building a SPA using vue.js, I need to assign a div background-image referencing something in the following path:
I'm trying to reference src/assets/img/firstCard.jpg but for some reason it doesn't shows the image, this is how I'm binding the image:
HTML:
<a class="card">
<div
class="card__background"
v-bind:style="secondCard">
</div>
<div class="card__content">
<p class="card__category">Gratuita</p>
<h3 class="card__heading">Ademas en diferentes plataformas.</h3>
</div>
</a>
JS:
<script>
export default {
data () {
return {
thirdCard: {
'background-image': require('#/assets/img/firstCard.jpg')
},
secondCard: {
'background-image': require('#/assets/img/firstCard.jpg')
},
firstard: {
'background-image': require('#/assets/img/firstCard.jpg')
}
}
}
}
</script>
Thank you all for your time.
You can try to make method or computed property:
getUrl (img) {
return require(`#/assets/img/${img}.jpg`);
}
then call that method in data object (for background-image you need to specify url):
data () {
return {
firstCard: {
'background-image': `url(${this.getUrl('firstCard')})`
}
}
},
My website allows users to video chat with one another, but currently the only way to change the video and audio source is the built in google method. I am trying to make it easier for users to change the video and audio source of the stream - is there an easy way to add this? i am showing the video source with :
<div class="show-model">
<!--<img src="/images/img1.jpg" class="img-response" ng-hide="isStreaming">-->
<div id="videos-container" room="{{$room}}" style="margin-top: 47px;"></div>
<div class="fullscreen-section" ng-show="isStreaming">
<div class="fullscreen-section__inner">
<div class="transparent-bg"></div>
<a class="cursor" title="full screen mode" ng-click="showFullScreen()" ng-show="!isFullScreenMode"><i class="fa fa-expand"></i></a>
<a class="cursor" title="compress screen mode" ng-click="notShowFullScreen()" ng-show="isFullScreenMode"><i class="fa fa-compress"></i></a>
</div>
</div>
</div>
And here is the directive for the stream.js
angular.module('matroshkiApp').directive('videoPlayer', ['$sce', function ($sce) {
return {
template: '<div><video ng-src="{{trustSrc()}}" id="streaming-{{videoId}}" autoplay class="img-responsive" height="130px"></video></div>',
restrict: 'E',
replace: true,
scope: {
vidSrc: '#',
showControl: '#',
vid: '#',
muted:'='
},
link: function link(scope, elem, attr) {
console.log('Initializing video-player');
scope.videoId = scope.vid;
scope.isMuted = scope.muted ? 'muted':'';
if(scope.isMuted){
jQuery(elem.context.firstChild).attr('muted',true);
elem.context.firstChild.muted = true;
}
scope.trustSrc = function () {
if (!scope.vidSrc) {
return undefined;
}
return $sce.trustAsResourceUrl(scope.vidSrc);
};
if (scope.showControl && elem.context && elem.context.firstChild) {
elem.context.firstChild.controls = true;
}
}
};
}]);
I have a picture grid and in the Mobile View (320 X 480), there is a "Load More" button. The container div is as follows:
<div id="divMoments" class="grid" data-masonry='{ "itemSelector": ".grid-item"}'>
<div class="grid-item">
<div class="gridContainer">
<img src="ImageURL" />
<p>OwnerName</p>
</div>
</div>
</div>
On the button click, it triggers an ajax call. The received result is a html string of many such grid items:
"<div class=\"grid-item\">imagex<div>
<div class=\"grid-item\">imagey<div>
..."
After appending the string to the container, I have the jQuery code to reload masonry, but all the images are overlapped. When I check the html, the masonry css is applied to all the items.
function GetNextSet() {
jQuery.ajax({
url: "/api/sitecore/Moment/GetNextSet",
type: "POST",
context: this,
success: function (data) {
ShowNextResultSet(data);
}
});
}
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}
using masonry v4.1.1
Re-applying masonry after a delay worked for me.
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
setTimeout(function () {
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}, 100);
}
I'm newbie at chrome extension. I'm making chrome extension that play youtube chromeless player.
It worked on chrome web browser. But, it isn't working on chrome extension.
I tested local .swf file. That is worked on chrome extension.
I think, chrome extension can't call onYouTubePlayerReady().
So I called window.onYouTubePlayerReady() after swfobject.embedSWF(). But, it isn't worked at ytplayer.loadVideoById("xa8TBfPw3u0", 0); with error message.
The error message was Uncaught TypeError: Object #<HTMLObjectElement> has no method 'loadVideoById'.
Is there a problem in manifest.json? Or in YouTube API? I don't know why isn't working on chrome extension.
popup.html is
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>YouTube Play</title>
</head>
<body>
<table width="1000" height="390">
<tr>
<td>
<div id="videoDiv">
Loading...
</div></td>
<td valign="top">
<div id="videoInfo">
<p>
Player state: <span id="playerState">--</span>
</p>
<p>
Current Time: <span id="videoCurrentTime">--:--</span> | Duration: <span id="videoDuration">--:--</span>
</p>
<p>
Bytes Total: <span id="bytesTotal">--</span> | Start Bytes: <span id="startBytes">--</span> | Bytes Loaded: <span id="bytesLoaded">--</span>
</p>
<p>
Controls: <input type="button" id="play" value="Play" />
<input type="button" id="pause" value="Pause" />
<input type="button" id="mute" value="Mute" />
<input type="button" id="unmute" value="Unmute" />
</p>
<p>
<input id="volumeSetting" type="text" size="3" />
<input type="button" id="setVolume" value="Set Volume" /> | Volume: <span id="volume">--</span>
</p>
</div></td>
</tr>
</table>
<script type="text/javascript" src="jsapi.js"></script>
<script type="text/javascript" src="my_script.js"></script>
<script type="text/javascript" src="swfobject.js"></script>
</body>
</html>
manifest.json is
{
"manifest_version": 2,
"name": "YouTube Player",
"description": "This extension is YouTube Player",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "http://*/*", "https://*/*", "background"],
"content_scripts": [
{
"matches": ["http://www.youtube.com/*"],
"js": ["my_script.js", "swfobject.js", "jsapi.js"]
}
]
}
my_script.js is
/*
* Chromeless player has no controls.
*/
// Update a particular HTML element with a new value
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
// This function is called when an error is thrown by the player
function onPlayerError(errorCode) {
alert("An error occured of type:" + errorCode);
}
// This function is called when the player changes state
function onPlayerStateChange(newState) {
updateHTML("playerState", newState);
}
// Display information about the current state of the player
function updatePlayerInfo() {
// Also check that at least one function exists since when IE unloads the
// page, it will destroy the SWF before clearing the interval.
if (ytplayer && ytplayer.getDuration) {
updateHTML("videoDuration", ytplayer.getDuration());
updateHTML("videoCurrentTime", ytplayer.getCurrentTime());
updateHTML("bytesTotal", ytplayer.getVideoBytesTotal());
updateHTML("startBytes", ytplayer.getVideoStartBytes());
updateHTML("bytesLoaded", ytplayer.getVideoBytesLoaded());
updateHTML("volume", ytplayer.getVolume());
}
}
// Allow the user to set the volume from 0-100
function setVideoVolume() {
var volume = parseInt(document.getElementById("volumeSetting").value);
if (isNaN(volume) || volume < 0 || volume > 100) {
alert("Please enter a valid volume between 0 and 100.");
} else if (ytplayer) {
ytplayer.setVolume(volume);
}
}
function playVideo() {
if (ytplayer) {
ytplayer.playVideo();
}
}
function pauseVideo() {
if (ytplayer) {
ytplayer.pauseVideo();
}
}
function muteVideo() {
if (ytplayer) {
ytplayer.mute();
}
}
function unMuteVideo() {
if (ytplayer) {
ytplayer.unMute();
}
}
// This function is automatically called by the player once it loads
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("ytPlayer");
// This causes the updatePlayerInfo function to be called every 250ms to
// get fresh data from the player
setInterval(updatePlayerInfo, 250);
updatePlayerInfo();
ytplayer.addEventListener("onStateChange", "onPlayerStateChange");
ytplayer.addEventListener("onError", "onPlayerError");
//Load an initial video into the player
ytplayer.loadVideoById("xa8TBfPw3u0", 0);
}
// The "main method" of this sample. Called when someone clicks "Run".
function loadPlayer() {
// Lets Flash from another domain call JavaScript
var params = {
allowScriptAccess : "always"
};
// The element id of the Flash embed
var atts = {
id : "ytPlayer"
};
// All of the magic handled by SWFObject (http://code.google.com/p/swfobject/)
swfobject.embedSWF("http://www.youtube.com/apiplayer?" + "&enablejsapi=1&playerapiid=ytplayer", "videoDiv", "640", "390", "8", null, null, params, atts);
//window.onYouTubePlayerReady();
document.getElementById("play").onclick = playVideo;
document.getElementById("pause").onclick = pauseVideo;
document.getElementById("mute").onclick = muteVideo;
document.getElementById("unmute").onclick = unMuteVideo;
document.getElementById("setVolume").onclick = setVideoVolume;
}
function _run() {
loadPlayer();
}
google.setOnLoadCallback(_run);
Please help me.
Recently I've encountered the same issue when working on a Chrome extension. When testing, the calls are simply not triggered. Until I've read this:
To test any of these calls, you must have your file running on a webserver, as the Flash player restricts calls between local files and the internet.
From YouTube's Player API Documentation