I'm trying to create a .mp3 player to just loop through audio tracks, but I keep getting error on Firebug that the main function I use is undefined, although I do define it. Here is the code:
$(document).ready(function() {
var counter=1;
var nextSong = function(){
if (counter <= 3) {
$('audio').src="audio/audio"+counter+".ogg";
$this.load();
$this.play();
counter++;
}
else {
counter=0;
$('audio').src="audio/audio"+counter+".ogg";
$this.load();
$this.play();
};
};
});
And my markup is simply:
<!DOCTYPE html>
<head>
<title>Dokimastiko Audio Player</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/dokimastiko.js"></script>
</head>
<body>
<audio src="audio/audio1.ogg" controls autoplay onended="nextSong();"></audio>
</body>
Any thoughts?
I debated on whether to give you a full lesson on why your code is pretty bad... And since I have little on my plate at work right now I'll do so... :P
First of all the $this you have there is undefined, so obviously calling a method on it is going to be undefined as well.
You probably copied the code from somewhere, which is fine, but you need to be able to copy is smartly instead of blindly.
.... you changed your code midway of my post, so update:
$(this) is the same as $(document) since that is the context of this within $(document).ready(function() {})
So, nope, still wrong.
So the first modification, it should be:
$('audio').load();
$('audio').play();
But actually that is still wrong. Because $('audio') is a jquery object, and it does not contain the DOM-level methods load and play directly, so you need to get the DOM object:
$('audio').get(0).load();
$('audio').get(0).play();
Now you would be wondering why the .get(0), it's because $('audio') is a collection of all the matches to 'audio', so get(0) would return the first one only.
This is prone to breakage if you decide to add more audio tags to the page, so you should give the audio tag a unique identifier:
<audio src="audio/audio1.ogg" controls autoplay onended="nextSong();" id="audio1"></audio>
And then use the id in your jquery selector:
$('#audio1').get(0).load();
$('#audio1').get(0).play();
This is still abit verbose, but given that you only need to do this, this is the simplest way.
UPDATE:
As per suggested by #JanDvorak here is a example that uses jquery events as well
Fiddle: http://jsfiddle.net/MpBP5/1/
jQuery(document).ready( function($) {
$('#audio1').bind('ended', function(e) {
alert('end');
});
});
I can also keep going on this "lesson", you should try not to define your music urls that abstractly, what if someone just leaves your page on and it hits a file which, for that counter #, doesn't exist?
I would declare an array of files you wish to load:
var library = [
'http://www.archive.org/download/bolero_69/Bolero.mp3',
'http://www.archive.org/download/MoonlightSonata_755/Beethoven-MoonlightSonata.mp3',
'http://www.archive.org/download/CanonInD_261/CanoninD.mp3',
'http://www.archive.org/download/PatrikbkarlChamberSymph/PatrikbkarlChamberSymph_vbr_mp3.zip'
];
var currentIndex = 0;
Then loop through the list:
jQuery(document).ready( function($) {
$('#audio1').bind('ended', function(e) {
currentIndex++;
if (currentIndex > library.length-1) {
currentIndex = 0;
}
this.src = library[currentIndex];
$('#url').html(library[currentIndex]);
});
$('#audio1').attr('src', library[currentIndex]);
$('#url').html(library[currentIndex]);
});
http://jsfiddle.net/MpBP5/3/
If you don't want a fixed list of audio files to play (which you really should), you can generate the array with at least some rules.
Related
I'm using the RoyalSlider plugin. I'm getting the DOM content of the current slide using the following code.
jQuery(document).ready(function($) {
var sliderS = $('.royalSlider').data('royalSlider');
sliderS.ev.on('rsAfterSlideChange', function(e, slideObject) {
var currentDOM = jQuery('.royalSlider').data('royalSlider').currSlide.content.context;
// I want to PLAY the <video> in the currentDOM variable here.
});
});
How does one go about selecting the < video > in the variable? I've tried everything from .getElementById() to .find(). Nothing is working. HALP!
To look at what I have going on: Current Sample
As you are using jQuery, what's wrong with simply using a video jQuery tag selector and supplying your DOM element as the context to search?
e.g.
var $video = $('video', currentDOM);
As your website does not appear to have videos, yet, I can't check this.
I am trying to fire a script when the contents of a div are altered, specifically when a div receives the next set of results from a js loaded paginator.
I have this:
<script script type="text/javascript" language="javascript">
document.addEventListener("DOMCharacterDataModified", ssdOnloadEvents, false);
function ssdOnloadEvents (evt) {
var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
function checkForJS_Finish () {
if ( document.querySelector ("#tester")
) {
clearInterval (jsInitChecktimer);
//do the actual work
var reqs = document.getElementById('requests');
var reqVal = reqs.get('value');
var buttons = $$('.clicker');
Array.each(buttons, function(va, index){
alert(va.get('value'));
});
}
}
}
</script>
This works well when the doc loads (as the results take a few seconds to arrive) but I need to narrow this down to the actual div contents, so other changes on the page do not fire the events.
I have tried:
var textNode = document.getElementById("sitepage_content_content");
textNode.addEventListener("DOMCharacterDataModified", function(evt) {
alert("Text changed");
}, false);
But the above does not return anything.
Can what I am trying to do be done in this way? If yes where am I going wrong?
Using Social Engine (Zend) framework with MooTools.
I did this in the end with a little cheat :-(
There is a google map loading on the page that sets markers to match the location of the results. So I added my events to the end this code namely: function setMarker() {}.
I will not mark this as the correct answer as it is not really an answer to my question, but rather a solution to my problem, which is localised to the Social engine framework.
I will add a Social engine tag to my original question in the hope it may help someone else in the future.
Thanks guys.
Quite a simple question, yet it has been bugging me all week!
Firstly, I do not expect someone to write me this huge piece of code, then me take it away and claim it for my own. Would prefer someone to actually help me write this :)
I am attempting to show a playlist on my website as a png image.
I have 2 playlists that must be shown.
The playlist will change on an image press.
I have 4 button images, 'CD1up', 'CD1down', 'CD2up' and 'CD2down'.
I would like to have these buttons changing what current playlist is being shown, but also showing the buttons correct state. For example, is playlist1 is being shown, then 'CD1up' must be shown, and 'CD2down' shown.
I would post my current code here, but I basically scrapped it all and decided to start from scratch since I'm terrible with web javascript.
All help is greatly appreciated!
I can basically fluent in HTML and CSS, but horrible at web javascript.
Some notes:
If you give each image an id attribute, you can use document.getElementById to get a reference to that element once the page is loaded.
Then you can set the src property on that element to a new URL to change the image.
Make sure your script tag is after the elements in the HTML (just before the closing </body> works) so that the elements exist when you want them.
You can add a click event handler to any element on the page. Most browsers support addEventListener but some older versions of IE still require you to use attachEvent to hook up the handler. So you see people with functions that look something like this:
function hookEvent(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler, false);
}
else if (element.attachEvent) {
element.attachEvent("on" + eventName, handler);
}
else {
element["on" + eventName] = function(event) {
return handler.call(this, event || window.event);
};
}
}
So for example, if you have this img:
<img id="myImage" src="/path/to/img.png">
This cycles through four images on click:
<!-- This must be AFTER the `img` above in the HTML,
just before your closing /body tag is good -->
<script>
(function() {
var myImage = document.getElementById("myImage"),
images = [
"/path/to/img1.png",
"/path/to/img2.png",
"/path/to/img3.png",
"/path/to/img4.png"
],
index = -1;
hookEvent(myImage, "click", imageClick);
function imageClick() {
++index;
if (index >= images.length) {
index = 0;
}
myImage.src = images[index];
}
})();
</script>
You can get a lot of utility functionality and smooth over browser differences using a decent library like jQuery, YUI, Closure, or any of several others, although if all you want to do on the page is change the images sometimes and handle a click or two, that might be overkill.
I'm fairly new to Javascript in general, and I cobbled together a small script from things found mostly on this site to try to get a small iframe to cycle through a bunch of links, which it does brilliantly. However, I also want it to stop cycling when the user clicks on the iframe or any of its contents.
Here is the code I have so far. There is only one iframe on the HTML page.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites = [
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var currentSite = sites.length;
var timerId;
var iframeDoc = $("iframe").contents().get(0);
$(document).ready(function ()
{
var $iframe = $("iframe").attr("src","side/html5.html");
timerId = setInterval(function()
{
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
$iframe.attr("src",sites[currentSite]);
}, 4000);
$(iframeDoc).bind('click', function()
{
clearInterval(timerId);
});
});
//-->
</script>
</head>
<body>
<sidebar>
<iframe name="sideframe" src="side/html5.html"></iframe>
</sidebar> ..etc..
Please help, I am trying to learn Javascript as fast as I can but as far as I can see, it should work, but it really doesn't.
Thanks for any help you can give me, it's really appreciated.
EDIT:
Okay, I've got a new script now, mostly based off of Elias' work, but it doesn't work either. I've pinned it down in Firebug and it's saying that the timerCallback.currentSite value IS updating properly, though I can't find the $iframe's src value to check for it explicitly. As far as I can tell, it is updating the variables properly, it's just not updating the iframe properly. Am I calling/setting the iframe correctly in this code? Also, is the linked in jquery library sufficient for my purposes? I'm a little lost of all these libraries to link to...
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites =
[
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var $iframe = $("iframe").attr("src","side/html5.html");
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
});
}
var timerId = setInterval(timerCallback, 4000);
//-->
</script>
If I were you, I'd play it safe. Since you say you're fairly new to JS, it might prove very informative.
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
}
var timerId = setInterval(timerCallback, 4000);
$($('iframe').contents().get('body')).unbind('click').bind('click', function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
Now I must admit that this code is not tested, at all. Though I think it provides a couple of things to get you on your way:
1) the interval is set using a callback function, because it's just better for tons of reasons
1b) in that Callback, I took advantage of the fact that functions are objects, and created a static var, that is set to either the length of your sites array (when undefined or 0), in both cases 1 is substracted
2) jQuery's ,get() method returns a DOM element, not a jquery object, that's why I wrapped it in $(), a new jQ obj, giving you the methods you need.
3) since you're manipulating the dom inside the iFrame, it's best to unbind events you want to bind
4) inside the iFrame, you don't have direct access to the parent window, where your interval is.
You might want to read up on how to deal with iFrames, because they can be a bit of a faff from time to time
EDIT:
David Diez is right, easiest way around this is to incorporate the binding in the timeout function:
function timerCallback()
{
timerCallback.currentSide = ...//uncanged
//add this:
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
//this needn't change
});
});
}
In theory, this should bind the click event to the body after it has been loaded
Edit2
I've been messing around a bit, you could keep your code, as is. just add a function:
function unsetInterval()
{
window.clearInterval(window.timerId);
}
and add this to your setInterval function:
$('#idOfIframe').load(function()
{
var parentWindow = window.parent;
$('body').on('click',function()
{
parentWindow.clearInterval();
});
});
this will get triggered as soon as the iFrame content is loaded, and bind the click event and unset the timer, like you wanted to
I think your code is not working because of this
var iframeDoc = $("iframe").contents().get(0);
This could be getting the header of the iFrame because you are saving the iframeDoc value to the first child of the iframe, the head tag, actually if you have more than 1 iframe in your window iframeDoc would be undefined because $("iframe") gets all the iframes of your document.
BTW your currentSite value condition is wrong, you asign the same value for both conditions
Now I give you an example:
<iframe id="myFrame" src="http://www.google.com/"></iframe>
and the script:
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var sites = [
"site1",
"site2"
];
var myFrame = document.getElementsByTagName('iframe')[0];
var currentSite = myFrame.getAttribute('src');
var timerId;
var myFrameDoc = window.frames[0].document;
$(document).ready(function()
{
myFrame.setAttribute('src', 'side/html5.html');
timerId = setInterval(function()
{
//WRONGG
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
myFrame.setAttribute('src', sites[currentSite]);
$(myFrame).off("click").on("click", clearInterval(timerId));
}, 4000);
//Won't work because you are trying to get events from an inside of a iframe
//$(myFrameDoc).on("click", clearInterval(timerId));
//This may work
$(myFrameDoc).off("click").on("click", clearInterval(timerId));
});
</script>
When you try to track the events of an iframe you have to be carefull because an iframe contains a totally different document for javascript purprouses so basically you have to get inside the new document, unbind the events you need to use, and bind them again against your functionality, as #Elias points out. but be aware that you are changing constantly the src of your iframe, so if yu really need to do that you will have to separate the code that unbinds and binds again your clearInterval, and for that matter maybe $.on() could work for you.
EDIT: Calling to the iframe should work this way IF the src of the iframe is inside the same domain, with the same port and with the same protocol:
var myFrameDoc = window.frames[0].document;
I Added a new variable because we want to bind and unbind the click event to the iframe's document, not to the iframe, we use for that the window.frames collection property, but modern browsers throw an exception and denies acces if you try to access to a frame and you are not on the same domain with using the same port and the same protocol...
Additionaly the use of $.on() and $.off() instead of $.bind and $.unbind() is because the first ones are the new ones and despite we are not using it here, they are capable of watch constantly the DOM for new elements to bind if added; that could be useful to this case if this code still doesn't work. If that is the case you can still change this:
var myFrameDoc = window.frames[0].window;
and this:
$(myFrameDoc).off("click", "document").on("click", "document", clearInterval(timerId));
This will re-bind the event handler to new documents additions. Not tested but could work.
I am trying to implement SoundManager 2 to play snippets of songs on this page.
This is my current JavaScript code:
alert('c!');
soundManager.url = 'http://www.transapine.ch/common/soundmanagerv297a-20120513/swf/soundmanager2.swf';
soundManager.flashVersion = 8; // optional: shiny features (default = 8)
soundManager.useFlashBlock = false; // optionally, enable when you're ready to dive in
/*
Example HTML to make sound snippet:
<div>
<img src="..." height="x" />
</div>
*/
alert('d!');
soundManager.onready(function() {
alert('e!');
var els = $.Elements.getElementsByClassName('sclip');
var a = url = '';
var clips = new Array();
var masterVolume = 100;
for (var i=0; i<els.length; i++) {
a = els[i];
url = a.href;
clips[i] = soundManager.createSound({
id: "clip" + i,
url: url,
volume: masterVolume
});//clips[i] = soundManager.createSound({
$.Events.add(a, "click", function(e) {
e.preventDefault();
clips[i].play();
});//$.Events.add(el, "click", function() {
$.CSS.removeClass(a, 'hidden');// show the button
}//for (var i=0; i<els.length; i++) {
});//soundManager.onready(function() {
And this is the section in the HTML page calling the necessary scripts:
<script src="http://assets.momo40k.ch/common/js/$-min.js" type="text/javascript"></script>
<script type="text/javascript">alert('a!'); //these alerts are for debugging</script>
<script src="http://assets.momo40k.ch/common/soundmanagerv297a-20120513/script/soundmanager2-nodebug-jsmin.js" type="text/javascript"></script>
<script type="text/javascript">alert('b!');</script>
<script src="http://assets.momo40k.ch/common/js/soundclips.js" type="text/javascript"></script>
<script type="text/javascript">alert('f!');</script>
Note: the $ library is a small library I use to even out the browser differences.
I have encountered several problems with this.
1. SWF files
In SoundManager's tutorial it says to use soundManager.url to tell it the location of the SWF files it needs. Whatever value I gave it, it seemed to ignore it, as Firebug gave me the following error:
NetworkError: 404 Not Found - http://www.transalpine.ch/portale/soundmanager2.swf
So I tried putting soundmanager2.swf in http://www.transalpine.ch/portale/, and the error disappeared, so I continued to see if I could get it to work like this.
Note: I have a base tag setting http://www.transalpine.ch/portale/ as the base URL in this section of the site.
Problems 2 and 3 sort of happened at the same time, I only managed to separate them through debugging the script little by little...
2. Script doesn't execute in certain conditions
After that, nothing happened. The two testing buttons I had put on the page weren't appearing as they should be ($.CSS.removeClass(a, 'hidden'); removes the class hidden from the elements, effectively showing them), so I went about working out what was executing and what wasn't in my usual way: alerts!
So I found out that soundclips.js wasn't executing at all, and then I found out that it could execute as long as lines 28-32 (clips[i] = soundManager.createSound({...});) were commented out. That puzzled me: how can something the browser hasn't even read yet prevent from reading that whole file?!
3. soundManager.onready doesn't fire
Having removed those lines, I still had a last problem, though probably it's caused by problem 1: the event soundManager.onready never fires.
Does anyone know what's wrong with my setup, and what's causing all these problems?
I'm guessing 2 and 3 both derive from 1, but I really don't understand 1 nor how 2 can be...
Thank you!
First off the URL should look like this:
soundManager.url = 'http://www.transapine.ch/common/soundmanagerv297a-20120513/swf/';
Everything else should somewhat be fixed now.