Disclaimer: Don't worry about my code being "standards compliant"
Basically, the page I am making is supposed to play a short audio clip upon loading using the <object data="someAudio.wav"> tag. I then use Javascript and setTimeout() to play a couple of other audio files after a few seconds of delay. The setTimeout does this by using innerHTML and rewriting the correct div section with with a new object, where the object is just another audio. For example:
<script type="text/javascript">
setTimeout("update_audio()", 2500);
function update_audio(){
document.getElementById('slide_audio').innerHTML="<object classid='clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95' height='0' width='0'><param name='FileName' value='../../../Audio_general/good.wav'><param name='autoplay' value='true'><object type='audio/mpeg' height='0' width='0' data='../../../Audio_general/good.wav'><param name='controller' value='true'><param name='autoplay' value='false'></object></object>";
}
</script>
I have the image linked to a map so that it is divided up into the 4 sections. When I click on a section, it will call a function that will perform logic based on my selection and then should play 1 of 2 other audio files. Section of map code here:
<map id="testing_image" name="pictureMap">
<area id="image1" shape="rect" coords="0, 0, 449, 331" onclick="evaluate_status(1);" onmouseover="this.style.cursor='pointer'" alt="FB">
</map>
My problem is, the onclick="evaluate_status()" parts of the map will only work before I update the innerHTML. Meaning, if I can click on a section before 2.5 seconds (the first innerHTML update) it will play the correct audio. However, after it updates the div section using innerHTML, none of the onclicks of my map will work. I am confused as to why this is since only a small section is being changed.
Can anyone help me figure out why the onclicks don't work and how I can fix it? I am still pretty new to web design and really need the assistance. Thanks!
You're missing a closing </div> tag for slide_audio, therefore testing_image in fact is a child of slide_audio and is being replaced with the new object when the script runs.
If you look in Firebug with JavaScript disabled you'll be able to see that testing_image is inside slide_audio, not separate from it. Here's a screenshot of Chrome's Developer Tools on that site:
Can you show of evaluate_status() function?
Also for the first code
setTimeout("update_audio()", 2500);
function update_audio(){
document.getElementById('slide_audio').innerHTML="";
}
You should define the function before you use it in settimeout. This will not generate error in Chrome, but in other browsers, it will.
Related
i want to write a chrome extention,which can control the video which i am seeing it in youtube.com,for example stop,play and pause it with a 'browser-action' buttons.
i tried alot to do it with javascript,as an example i wrote a code like this;
var btn=document.getelementbyid('the button id');
var video=document.getelementbyid('video'); //current video on youtube which is playing
btn.addeventlistener('click',function(){
video.stop()
})
i always get this error=>video.stop() is not a function...
my question is why i am getting this error?
my second question is can i wrap the video element with an iframe tag (not by loading the video into another page,just in youtube.com) and control it right there?
Try this in the console while on a video page:
document.getElementById('movie_player').pauseVideo()
or
document.getElementById('movie_player').playVideo()
This should work.
Please note that getElementById is not the same as getelementbyid in Javascript! Also it's addEventListener, not addeventlistener. Function and variable names are generally in camelCase in Javascript.
I want to use the YouTube Player API to call a single function that will stop an embedded YT video (loaded dynamically on the page with JS and jQuery) from playing on a button click.
I'm admittedly (very) new to working with APIs for web development and despite reading through several of the other answers (such as here, here and here), I am still confused as to the necessity of the different JS components.
I have a code block that is dynamically appended multiple times to the HTML page, with the YouTube URL changing for each entry based on a separate JSON file. The added code is as follows...
<li>
<section class="youtube-video">
<iframe src="'theLoadedURL'?enablejsapi=1&rel=0" frameborder="0" allowfullscreen="1">
</iframe>
</section>
</li>
... and then I have added the <script> tag at the bottom of the <body> that loads(?) the API...
<script src="https://www.youtube.com/iframe_api"></script>
... and finally a simple button for demonstration.
<button> Stop Video </button>
I was hoping that there would be a way to then simply call the player.stopVideo(); function from the API and have it affect the already-embedded iFrame on the button click, something like...
$('button').on('click', function () {
$('.youtube-video iframe').stopVideo();
});
... but alas, it doesn't seem to be that simple!
The documentation and other answers appear to suggest defining various variables and functions for the player, or deal with loading videos manually (rather than dynamically, as in this case); but it seems unnecessarily complex for an element that is already loaded on the page - is there something that I'm missing or an obvious way of simplifying things?
Detailed answers would be much appreciated as I'm still getting to grips with JS in general.
Thanks! :)
So from playing around with New's fiddle from the comments, I believe I have found the simplest way of implementing the Youtube Player API, in my situation.
Firstly, it requires minor editing the HTML <li> code block that, in practice, would be loaded dynamically onto my page:
<li>
<section class="active">
<iframe id="youtube-video" src="https://www.youtube.com/embed/y1yFiotx3qk?
rel=0&modestbranding=1&showinfo=0&enablejsapi=1" frameborder="0"
allow="autoplay; encrypted-media" allowfullscreen></iframe>
</section>
</li>
The main changes come from the addition of a class of .active being added to the <section> tag to specify the current video targeted by the YouTube Player API. The iframe then has an id of #youtube-video. It should be noted that all ids and classes are completely arbitrary.
At the bottom of the HTML's <body> I have added the API script...
<script src="https://www.youtube.com/iframe_api"></script>
... however, found that it is important that this is placed above all other <script> tags in the same location.
Following this, I have set up my JS file (with jQuery) as follows:
$(document).ready(function () {
// Creates arbitrary global 'player' variable to be defined later
var player;
function onYouTubeIframeAPIReady() {
setTimeout(function() { //Using this as seemed to come across occasional bugs in Chrome
console.log('API Loaded!')
// Selects first <li> tag iframe contained in a section with the class of '.active'
var $selectedVideo = $('.active #youtube-video')[0];
// Uses the previous variable to define the youtube player
player = new YT.Player($selectedVideo);
}, 100);
}
// Calls the Function
onYouTubeIframeAPIReady();
});
Finally, also within the $(document).ready() function, I am able to bind the relevant YouTube Player API event handlers to the <button> HTML element:
$('button').on('click', function(){
player.stopVideo();
});
The intention behind my code is to form part of a slideshow, and thus there should only be one section that has the .active class at any one time and this can be used to select different videos on different slides.
I've put together an example JSFiddle here that contains a better UI and more in-depth comments, which may be useful to someone in future.
I want to print a different content from my web page that includes an image. So is my JavaScript code:
function print() {
var w = window.open();
w.document.write(....);
// time for rendering images
setTimeout(function () { w.print(); w.close();},10);
}
Google Chrome shows a new tab, with no print dialog. When I exit the tab and return it, the print dialog shows!
When I take out the 10 ms timeout, it not shows my image (there is no time for rendering the image), but the dialog shows instantly.
Maybe, someone will tell me: Creates HTML using DOM functions like createElement and appendChild. So you don't need rendering time and it is neater.
Therefore I did an alternative with whole HTML content created from scratch
I've used the src dinamic assigment for my image
ele.setAttribute("src","LogoUp.png"); // ele is an image element
instead using a static HTML with same src value
<img id="header" style="margin-left: auto;
margin-right:auto;" src="LogoUp.png" >
PS: My Chrome is updated (v.63)
Now there is no need for rendering time and I can extract the setTimeout function call, however the image is not loading. It's very weird. I saw it in the Chrome DevTools, the official Chrome debugger tool. It shows a right string, but no image is pointed.
I'm using a local computer with Windows 7 and the image is in the same directory as the html source.
So I'm crazy ...
Update:
I also have tried, with no success: (I also saw the html in Chrome DevTools )
c.appendChild(document.getElementById("header").cloneNode(true))
// where c is the image's parent element
It's amazing because the original image works, when using innerHTML
I've made more research and I've discovered a great solution without the need for a popup tab. The magic was made by iFrame. An empty one:
<iframe id="luck" style="border:none;" >
</iframe>
In other point, I've placed the content to be printed (with images)
<div class="printer" style="margin:0; padding:0; display:none">
...
</div>
Display is set with "none" (since I don't want to display that content on the page).
The print code is below in just 2 lines (long ones):
function procPrint() {
document.getElementById("luck").contentDocument.body.innerHTML =
document.getElementsByClassName('printer')[0].innerHTML;
setTimeout(function() {luck.contentWindow.print();},10);
// just 10 ms waiting time is enough,
// maybe complex content demands more.
}
Advantages:
No popup. Cancel or OK resumes the original page.
Print dialog is not missing. No tab to be changed.
Disadvantages:
Rendering of innerHTML assignment demands setTimeout use.
Firefox does not give an error, but the printing does not work. My goal is just a prototype. So for me, I'm ok.
-/-
I did not testing the src bug (correct string don't display the image) with DOM assignments.
I'm satisfied with what I got. I hope it will be useful for someone.
Update:
I've discovered that iFrame printing ignores completely CSS resources like a printing CSS file:
<link rel="stylesheet" type="text/css" href="/print.css" media="print" />
or #media print specs inside a CSS file like:
#media print {
body { font-size: 14pt }
}
It occurs because logically the frame is another document. So the style needs to be attached in the HTML that will be cloned inside iFrame or it's possible includes css file dinamically in the child after cloning HTML inside the iFrame (see here).
My brain understand the logic, but it's weird: If you puts a style in the HTML printing source it works, but if you use the class name in the CSS file, it changes the clone source but not in the cloned nodes.
If one needs to change or set the background color (or image) in the printing, changes directly in the body iframe. One specifies background color in the cointaner doesn't make the work.
In this case, add the below line in procPrint function above.
d.style.backgroundColor = "#FF0000";
Update 2
For invisible iFrame on the screen uses:
#media screen{
.printonly, .printonly * {
display: none !important;
}
}
I would like, when navigating away from the page, to execute a fade of a musical cue instead of cutting if off abruptly. It is okay with me if the fade adds a half second to the time needed to execute the link.
I have the following code that will execute a fadeout of a playing music cue.
<audio id="myAudio"
<source src="./audio/pluto.mp3" type="audio/mp3">
Your browser does not support the audio element.
</audio>
and
<script>
function fadeAudio()
{
if (myAudio.volume > 0)
{
myAudio.volume = Math.max(0, myAudio.volume - 0.05);
setTimeout(fadeAudio, 20);
}
}
</script>
I tested this code with a button, and it works fine (sometimes there is a bit of zippering, but I prefer it to an abrupt cutoff).
<button onclick="fadeAudio()">Try it</button>
My problem is that I don't know how to call and execute this fade before navigating away. I was looking at html's onbeforeunload, but that seems to be geared entirely to printing a warning prompt, with no way to insert my intervening fadeAudio() function.
Simply doing the following accomplished nothing:
<body onbeforeunload="fadeAudio()">
And this didn't work with onunload either.
I am thinking another approach would be to rewrite the links on the page to run the fadeAudio() function first. (It's more important to me that transitions between my pages sound nice than if the user decides to close or go elsewhere.) Perhaps this can be done via making a button and calling the fadeAudio and a linking function in sequence. But it seems there might also be a neater way. Any suggestions?
Here is what I found that kind of works:
(1) in the link, one can call a function
(2) in the function, I first call the fadeAudio() function, then I call a setTimeout() function with 1000 ms time allotted to allow the fadeAudio() to complete
(3) then the setTimeout calls a window.open() method of the target link.
I'm going to be tweaking the various timings to see how far I can tighten this without adding too much zippering. It will definitely make things a little sluggish going from location to location on my site though.
Wouldn't it be nice if there was a way for the sound to just fade out in its own thread while the new page appears. If there is a way, I would love to know about it.
In the script tag:
function linkToHome()
{
fadeAudio();
setTimeout(openHome, 1000);
}
function openHome()
{
window.open('index.htm','_self');
}
The URL call in HTML:
Home
Will probably try to figure out a way to paramaterize the above to allow the method or tag to include the target URL.
I use one of those jQuery libraries, Fancybox, to make images show up in a modal pop-up style thing on top of the text. This works fine for mostly everything, however! When placing an image in TinyMCE and selecting "caption" and then making the image a link, the code Plone generates ends up having two of the same links, which result in a weird "Fancybox gallery slideshow" of the same image repeated twice. Here's why —
HTML from within TinyMCE:
<p><a class="internal-link" href="resolveuid/af2954f5af084d5aa359a480b33c5368" target="_self" title="Test test test"><img class="image-left captioned" src="resolveuid/af2954f5af084d5aa359a480b33c5368/##images/image/med" /></a>
HTML generated when viewing the page:
<dl class="image-left captioned" style="width:300px;">
<dt>
<a class="internal-link" target="_self" href="http://127.0.0.1:8081/CAES/images/alison-king.jpg" title="Test test test" rel="gallery"><img width="300" height="200" title="alison king" alt="alison king" src="http://127.0.0.1:8081/CAES/images/alison-king.jpg/##images/98443898-0834-45ea-b724-8f40a0c92e0c.jpeg"></a>
</dt>
<a class="internal-link" target="_self" href="http://127.0.0.1:8081/CAES/images/alison-king.jpg" title="Test test test" rel="gallery"><dd class="image-caption" style="width:300px;">test</dd>
I get why this happens and it's clever, but doesn't work for my purposes. Does anyone know where this code is generated in the ZMI? Or, any ideas on a jQuery solution to target all links except for that second one? Here's my existing Fancybox code:
<script type="text/javascript">
$(document).ready(function() {
/* Simple image gallery. Uses default settings */
$("a[href$='.jpg'],a[href$='.png'],a[href$='.gif']").attr('rel', 'gallery').fancybox();
});
</script>
It will work with the following code, but then it only applies Fancybox to the first image link of a captioned image, and won't apply to any other non-captioned images.
<script type="text/javascript">
$(document).ready(function() {
$("dl.captioned dt a").attr('rel', 'gallery').fancybox();
});
</script>
And lastly, I tried to apply Fancybox to everything and then afterwards remove it from just the second dl.captioned link with jQuery, but can't quite get it, this still resu:
<script type="text/javascript">
$(document).ready(function() {
$("a[href$='.jpg'],a[href$='.png'],a[href$='.gif'],a[href$='/image']").attr('rel', 'gallery');
$("dl.captioned > a").attr('rel', '');
$("a[rel$='gallery']").fancybox();
});
</script>
Thanks!
I cannot exactly reproduce the output you get, however can reproduce the doubled images in the gallery.
The doubling results, because the inserted image will be wrapped in a link to the image-file automagically (another JS, assumingly applied by TinyMCE), when you enable the captioning.
So, to resolve your request, it should be sufficient to NOT mark the images as links manually, when using the captioning anyway.
Nota: As you are using the <script>-tag, it seems you insert the JS in a template, yet it is recommended to embed it as a link in the header via JS-registration, especially, if you want this to happen globally. Alternatively add an expression-attribute in the registration, to restrict when the script should be delivered. If you have special reasons to only have this in a certain template, it is recommended to use the javascript-slot. Insert JS via a <script>-tag at the bottom of a document in order to execute it after the DOM is loaded, isn't necessary anymore, respectively discouraged, we can use document.ready (or window.onload) instead.
Steps I took to reproduce: Create a site, enable captioning via TinyMCE's controlpanel, install collective.fancybox, install a product of my own with a registered Javascript and insert:
(function($) {
$(document).ready(function() {
// Look for all links in content-area,
// add rel-attribute to make it a gallery.
// Skipped distinction of whether it's an image or not, 'cause I'm
// louzy lazy and you know how to DIY anyway ;)
$("#content-core a").attr('rel', 'gallery').fancybox();
});
})(jQuery);