I'm trying to figure out how to combine this code into a switch statement using an index. I'm using this code to allow someone to click on a thumbnail, play that video in the player along with change the title depending on which video is played. Thanks in advance.
<script>
// Play the video
$( "#video-1, #item1" ).click(function() {
flowplayer().play("video1.mp4");
});
$( "#video-2, #item2" ).click(function() {
flowplayer().play("video2.mp4");
});
$( "#video-3, #item3" ).click(function() {
flowplayer().play("video3.mp4");
});
$( "#video-4, #item4" ).click(function() {
flowplayer().play("video4.mp4");
});
$( "#video-5, #item5" ).click(function() {
flowplayer().play("video5.mp4");
});
// Change title
function changeTitle(name)
{
document.getElementById("show-title").innerHTML = "Now playing " + name;
}
// Add and remove active class
$('#playlist li').on('click', function(){
$(this).addClass('active').siblings().removeClass('active');
});
</script>
The cleanest way to do this is to add a common class name to all the items that you want to be video click enabled (all the #itemX and #video-X elements) so then you can use a very simple piece of javascript for the common click handler. You then extract the digits out of the click on element's ID value in order to figure out which video to play:
$(".videoPlay").click(function {
var num = this.id.match(/\d+/)[0];
flowplayer().play("video" + num + ".mp4");
});
If you cant add the common class, then you can just list out all the selectors you want included:
$("#video-1, #video-2, #video-3, #video-4, #video-5, #item1, #item2, #item3, #item4, #item5").click(function() {
var num = this.id.match(/\d+/)[0];
flowplayer().play("video" + num + ".mp4");
});
Or, if you have no other ids that might get caught up in a partial id match, you can use the starts with selector logic, though I prefer to avoid this because it's not fast for the browser to resolve (it has to look at every single object that has an ID). I'd perfer listing the actual ids or using a common class name:
$("[id^='video-'], [id^='item']").click(function() {
var num = this.id.match(/\d+/)[0];
flowplayer().play("video" + num + ".mp4");
});
If there is no correspondence between the id of the clicked-on item and the video filename, then you need to create some sort of map between the two. My favorite technique would be to specify a data-video custom attribute on the actual element:
<div class="videoPlay" data-video="thor.mp4">Click me to Play a Video</div>
And, then the JS would be:
$(".videoPlay").click(function {
var fname = $(this).data("video");
flowplayer().play(fname);
});
You can have as many of these HTML elements as you want and just make sure each one specifies the video file you want that element to play and the JS doesn't have to change at all as you add more and more.
This should work :
$( "[id^='video-'], [id^=item]" ).click(function() {
var vid = this.id.replace(/(\d)|./g, '$1');
flowplayer().play("video"+ vid +".mp4");
});
Related
I'm new to jQuery and JS. How can I rewrite these functions correctly using jQuery? I know it's standard JS which was working fine with the manual HTML markup but I now also need to go through page and find iframes with YouTube src and take ID and then recreate them with the first example markup.
I'm totally stuck. I think I have it more or less, but not sure where to go to now.
Fiddle: https://jsfiddle.net/yurt5bb6/
First example uses my markup:
<div class="video-container">
<div class="video-player" data-id="Cv_2mp3X868"></div>
</div>
Which works as I need, however I think now I need to foreach on load and create that same markup from iframe embeds the functions should be better.
Attempt:
function createThumb(id) {
return '<img class="youtube-thumb" src="//i.ytimg.com/vi/' + id + '/hqdefault.jpg"><div class="play-button"></div>';
}
function createIframe() {
var iframe = $("iframe");
iframe.attr("src", "//www.youtube.com/embed/" + this.parentNode.dataset.id + "?autoplay=1&autohide=2&border=0&wmode=opaque&enablejsapi=1&controls=0&showinfo=0");
iframe.attr("frameborder", "0");
iframe.attr("id", "youtube-iframe");
this.parentNode.replaceChild(iframe, this);
}
$(document).ready(function() {
// build video from default markup
var defaultVideo = $(".video-player");
$(defaultVideo).each(function (index, value){
var p = $('<div></div>');
p.innerHTML = createThumb(v[n].dataset.id);
p.onclick = createIframe;
v[n].appendChild(p);
});
// search for social embeds and recreate to our markup
$('iframe[src*="youtube.com"]').each(function() {
var loadedVideoURL = $('iframe').attr('src').match(/[^/]*$/)[0];
console.log(loadedVideoURL);
});
});
I've tried to clean up the messy mix of native JS and jQuery and made some edits to your fiddle: https://jsfiddle.net/yurt5bb6/2/
Default function:
(function() {
$.each($('.video-player'), function() {
$(this).append(videoThumb($(this).data('id')));
$(this).on('click', videoIframe);
});
$.each($('iframe'), function() {
// Rebuild the given template
var player = $('<div class="video-player">');
// Strip youtube video id for data-id attribute
var id = $(this).attr('src');
id = id.substr(id.lastIndexOf("/")+1);
player.attr('data-id', id);
player.html(videoThumb(id));
player.on('click', videoIframe);
var videoContainer = $('<div class="video-container">');
videoContainer.append(player);
$(this).replaceWith(videoContainer);
});
})();
Iframe render function:
function videoIframe() {
var iframe = $('<iframe>');
iframe.attr("src", "//www.youtube.com/embed/" + $(this).attr('data-id') + "?autoplay=1&autohide=2&border=0&wmode=opaque&enablejsapi=1&controls=0&showinfo=0");
iframe.attr("frameborder", "0");
iframe.addClass("youtube-iframe");
$(this).empty();
$(this).append(iframe);
}
Also changed the CSS, made a class instead of id for youtube-iframe.
I've got a little code snippet to 'hack' away at some templated code I can't fix normally.
<script>
jQuery( document ).ready(function() {
jQuery(".avatar").each(function() {
var text = jQuery(this).attr("src");
text = text.replace("-64x64.jpg", ".jpg");
text = text.replace("-80x80.jpg", ".jpg");
text = text.replace("-32x32.jpg", ".jpg");
text = text.replace("-28x28.jpg", ".jpg");
text = text.replace("-16x16.jpg", ".jpg");
text = text.replace("-128x128.jpg", ".jpg");
jQuery(this).attr("src", text);
});
});
</script>
Upon this script above firing in the browser I'm getting the following error in the console:
TypeError: text is undefined
text = text.replace("-64x64.jpg", ".jpg");
Racking my brain but coming up with nothing. Tried using var text; to try and define it at the start of the script and also tried using a different variable name in case it was conflicting with something both of which did nothing....
This means that at least one of the elements with class avatar does not have a src attribute. attr returns undefined if the element in question doesn't have the attribute at all.
You can put a guard in (if (text)). Here's an example. Also note that there's zero reason to use jQuery(this).attr("src"); just use this.src:
jQuery( document ).ready(function() {
jQuery(".avatar").each(function() {
if (this.src) {
this.src = this.src.replace("-64x64.jpg", ".jpg")
.replace("-80x80.jpg", ".jpg")
.replace("-32x32.jpg", ".jpg")
.replace("-28x28.jpg", ".jpg")
.replace("-16x16.jpg", ".jpg")
.replace("-128x128.jpg", ".jpg");
}
});
});
You can also probably make that code a bit more robust using a regular expression:
jQuery( document ).ready(function() {
jQuery(".avatar").each(function() {
if (this.src) {
this.src = this.src.replace(/-(\d+x\d+)\.jpg$/, ".jpg");
}
});
});
That will replace -DIGITSxDIGITS.jpg with .jpg, without being specific about what the digits in each case are. \d means "any digit", and the + after it means "one or more".
If you take a look at this page here, you'll see that I've created a bit of a Youtube video gallery. When it works, it should replace the video in the main section of the page (at the top) with the thumbnail that is clicked and the text on the right is also replaced with text related to that video.
The text replacement seems to be working perfectly but I'm experiencing an issue where during the swap, the iFrame seems to be getting placed multiple times and so the video plays 2-3 times.
The Javascript is below -- is this something I've missed?
<script>
function replaceVideo(id) {
originalSrc = jQuery("iframe", "#" + id).attr("src");
autoPlay = originalSrc + "&autoplay=1";
jQuery("iframe", "#" + id).attr("src", autoPlay);
video = jQuery(".video-wrap", "#" + id).html();
jQuery(".flex-video").html(video);
text = jQuery(".video-description", "#" + id).html();
jQuery(".vid_desc").html(text);
jQuery("iframe", "#" + id).attr("src", originalSrc);
}
jQuery(".video-list li").click(function() {
id = jQuery(this).attr("id");
replaceVideo(id);
});
jQuery(window).load(function() {
if(window.location.search.substring(1)) {
element = window.location.search.substring(1).split('&');
if (document.getElementById(element[0])) {
document.onload = replaceVideo(element[0]);
}
}
});
</script>
Thanks!
Run jQuery(".flex-video") this in your javascript console. You'll see there are THREE divs that have that class. So jQuery(".flex-video").html(video); this line of JS changes the inner HTML of 3 elements to be the iframe.
<div class="flex-video widescreen">
<iframe width="583" height="328" src="http://www.youtube.com/embed/TWmFCX40BQc?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe>
</div>
You need to make the above div distinguishable from the other flex-video frames. Give the parent div an id or another class or something to query off of. Do that, and then you'd be fine.
EDIT: By the way, this code is wrong:
if(window.location.search.substring(1))
{
element = window.location.search.substring(1).split('&');
if (document.getElementById(element[0])) {
document.onload = replaceVideo(element[0]);
}
}
setting document.onload to a function call will call replaceVideo and set the onload property to whatever it returns, which is nothing. It may appear to work because the video plays, but that's just because you're calling the replaceVideo method. Setting your if to this, will probably be sufficient for you (unless you can explain why you're setting it to onload)
if(document.getElementById(element[0]))
replaceVideo(element[0]);
So,
I'm trying to come up with a way to dynamically load content into multiple tabs, where each tab can contain anywhere from one to several elements (reports).
Currently, the reports are loaded on page load with jQuery $.load. I'm using Bootstrap and bootstrap tabs. I found a site that teaches how to load multiple tabs, but not specifically what I need to do. That site is here: http://www.mightywebdeveloper.com/coding/bootstrap-2-tabs-jquery-load-content/
In contrast, each tab is set up more like this:
<div id="tab1">
<div id="report1"></div>
<div id="report2"></div>
</div>
I cannot use the top-level div to load the content, because it will potentially have multiple children. I need to loop through the div's, use regex to parse the ID, and load each report when the tabs are changed.
I haven't yet figured out the regex expression, but it should be fairly simple - the element id will be something like this : "#be78f5aa3-25". This is an alphanumeric 9-character dbid, followed by a hypen, followed by a 1-3 digit integer (not starting in 0). Then I need to split those two strings into separate variables and inject them into an API call.
Anyone looking to load multiple pages into bootstrap tabs may find this of use. I was able to get it working using some regex (specific to my application), placing div's within the tab-pane container's that had an Element Id which could be used to create the report I wanted to load into the container using $.load. I also added a few things for persistent tabs when the user went to another page and then used the back button, and another condition to load the content in the first tab if there was no hash in the URL.
I'm sure it could be cleaned up, but you get the gist..
$(function() {
"use strict";
var baseURL, $navbox;
baseURL = window.location.protocol + "//" + window.location.hostname + "/db/";
$navbox = $("#myTabs");
$navbox.bind("show", function(e) {
var contentID, pattern, selectDiv;
pattern = /#(\Btab|tab\B)?(\Bdropdown|dropdown\B)?([1-9]{1}[0-9]*)/i;
contentID = e.target.toString().match(pattern)[0];
selectDiv = contentID + " > div";
return $(selectDiv).each(function() {
var parts = this.id.match(/(##enter regex here)/);
if (parts) {
$(this).load(baseURL + parts[0]);
return;
}
return $("#myTabs").tab();
});
});
if (window.location.hash) {
$('#myTabs').find('a[href="'+window.location.hash+'"]').tab('show');
}
else {
var elemID = "#"+$('[class^="tab-pane active"]').attr('id') + " > div";
$(elemID).each(function() {
var parts = this.id.match(/(##enter regex here)/);
$(this).load(baseURL + parts[0]);
return $("#myTabs").tab();
});
}
});
$('#myTabs a').click(function (e) {
e.preventDefault();
var bob = jQuery(this).attr("href");
bob = jQuery.trim(bob);
if(bob == "" || bob == "javascript:void(0)") {
return;
}
else {
window.location.hash = $(this).attr('href');
$(this).tab('show');
}
});
I have an img html block <img src="folder1/folder2/folder3/logo1.png"> positioned inside a big div like this
<div id="editorial">
<div id="img_editorial"><img src="folder1/folder2/folder3/logo1.png" /></div>
</div>
When user hovers the <div id="editorial"> (mouseover) i want to read the attribute of <img> which is folder1/folder2/folder3/logo1.png extract the logo1.png from this and add on_ to the logo ( on_logo1.png ) and then output it with jquery .html() function to overwritte <div id="img_editorial">
On mouseout i want to return to logo1.png ... because i have multiple background changes in that parent div ... so the basic functionality is to grayout a logo when mouse is over a big div (also div`s background changes ... etc) ...
So .. how can i read the <img> attribute and then extract logo1.png and not the whole folder1/folder2/folder3/logo1.png ...
You can read the attribute like this:
var img_src = $('#img_editorial img').attr('src');
This will give you:
folder1/folder2/folder3/logo1.png
Than you can split it with:
var split_img_src = img_src.split('/');
This will give you an array, something like:
split_img_src[0] = folder1;
split_img_src[1] = folder2;
split_img_src[2] = folder3;
split_img_src[3] = logo1.png;
so the last value in the array should always be the name of the file - no matter how long the directory tree is.
So you now have the file name, you can append what ever you want to it and do what ever you need.
Good luck.
Here! just a nice solution:
$('#img_editorial img').hover(function(){
imgSrc = $(this).attr('src');
var imgSplit = imgSrc.split('/');
var imgName = imgSplit[3];
$(this).attr('src', imgSrc.replace(imgName, 'on_'+imgName) );
},function(){
$(this).attr('src', imgSrc);
});
If you want, open Firebug and play with this DEMO
The following should do what you want. It just stores the original image using the jQuery .data() API and puts it back when on .mouseleave() of the <div>.
$('div#editorial').mouseenter(function() {
var originalSrc = $('img', this).prop('src');
$(this).data('originalSrc', originalSrc);
var pathComponents = originalSrc.split('/');
var logo = pathComponents.pop();
pathComponents.push('on_' + logo);
$('img', this).prop('src', pathComponents.join('/'));
}).mouseleave(function() {
$('img', this).prop('src', $(this).data('originalSrc'));
});
The demo sort of works but I have no _on image so it just 404s. I hope you get the idea :-)