Put a button in certain spot of page? - javascript

i am fairly new to coding and i got this typing script online and then created a button, the button links to a different page that I haven't created yet. The issue i am facing is that i cant get the button to stay in one place while the typing script is running, it moves around, is there a way i can put it in a fixed position maybe by the bottom left of the screen. my code is bellow, Thanks!
var TxtType = function(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtType.prototype.tick = function() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';
var that = this;
var delta = 200 - Math.random() * 100;
if (this.isDeleting) {
delta /= 3;
}
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 5000;
}
setTimeout(function() {
that.tick();
}, delta);
};
window.onload = function() {
var elements = document.getElementsByClassName('typewrite');
for (var i = 0; i < elements.length; i++) {
var toRotate = elements[i].getAttribute('data-type');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtType(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".typewrite > .wrap { border-right: 0.08em solid #fff}";
document.body.appendChild(css);
};
.button {
position: relative;
left: 20%;
right: 20%;
bottom: 5%;
top: 60%;
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 24px 80px;
border: 1px solid #a12727;
border-radius: 98px;
background: #bd4aff;
background: -webkit-gradient(linear, left top, left bottom, from(#bd4aff), to(#992727));
background: -moz-linear-gradient(top, #bd4aff, #992727);
background: linear-gradient(to bottom, #bd4aff, #992727);
-webkit-box-shadow: #ff5959 0px 0px 40px 0px;
-moz-box-shadow: #ff5959 0px 0px 40px 0px;
box-shadow: #ff5959 0px 0px 40px 0px;
text-shadow: #591717 1px 1px 0px;
font: normal normal bold 37px arial;
color: #ffffff;
text-decoration: none;
}
.button:hover,
.button:focus {
background: #e359ff;
background: -webkit-gradient(linear, left top, left bottom, from(#e359ff), to(#b62f2f));
background: -moz-linear-gradient(top, #e359ff, #b62f2f);
background: linear-gradient(to bottom, #e359ff, #b62f2f);
color: #ffffff;
text-decoration: none;
}
.button:active {
background: #712c99;
background: -webkit-gradient(linear, left top, left bottom, from(#712c99), to(#982727));
background: -moz-linear-gradient(top, #712c99, #982727);
background: linear-gradient(to bottom, #712c99, #982727);
}
.button:after {
content: "\0000a0";
display: inline-block;
height: 24px;
width: 24px;
line-height: 24px;
margin: 0 -4px -6px 4px;
position: relative;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABBUlEQVRIibXVMUrEQBQG4I9FrMXKUjyBhVjZeAULD7F2VoLHELEQKzsvINZWgldwFQutLCwWRFhisQ6Mw2Yzk4mvfC+8L/OTIfytMd6x65/qDA0+sDPEwlFLfx13QyBtQIxUxbUMCMitipN0AQHpHVcOECPFceUCASmOqwQISFFcpUCMZMXVBwhIVlx9gYB0xlUDxEhrXLVAQFrjGgIIyMWiwUqPZd84xVfSfxwKWMUrbnIezonoBW9J7yj3bbqACfZxnvT3sJ2LxBX+aA2esPXb38A0mjW4rAGesZnMrhNgirVS4BD3C5Yzv0yzBDkuBZbVCA/R8hlOhgTgAJ+4Mr+5nV/hD3mmNbSMQ+JfAAAAAElFTkSuQmCC") no-repeat left center transparent;
background-size: 100% 100%;
}
<!doctype html>
<html>
<head>
<style>
body {
background-color: #ce3635;
text-align: center;
color: #fff;
padding-top: 10em;
}
* {
color: #fff;
text-decoration: none;
}
</style>
<script src="js/script.js">
</script>
</head>
<body>
<h1>
<a href="" class="typewrite" data-period="1000" data-type='[ "Hi, Welcome to DShroff.com", "A Website created entirely from scratch by me.", "Click the button below to go to games or wait here to be redirected to home."]'>
<span class="wrap"></span>
</a>
<a class="button" style="vertical-align:middle;margin:50px 0px" href="https://games.dshroff.com">Click to go to Games</a>
</a>
</a>
</h1>

You can just change the position: relative; to position: absolute; of button . Button will get out of flow from document and will appear below the text

Did you try using position:fixed?
https://www.w3schools.com/css/css_positioning.asp
And then manipulate top and left.
Ah, maybe more important, put the button inside div, and style the div.

Related

javascript on a webpage displaying text wrongly

I have JS code on a webpage that loads questions in from mysql db and displays the text . What happens is that it cuts off words at the end of the line and continues the word on the next line at the start. So all text across the screen starts/ends at the same point.
This seems to be the code where it displays the text.
For example the text will look like at the end of a line 'cont' and then on next line at the start 'inue'.
How do i fix this?
var questions = <?=$questions;?>;
// Initialize variables
//------------------------------------------------------------------
var tags;
var tagsClass = '';
var liTagsid = [];
var correctAns = 0;
var isscorrect = 0;
var quizPage = 1;
var currentIndex = 0;
var currentQuestion = questions[currentIndex];
var prevousQuestion;
var previousIndex = 0;
var ulTag = document.getElementsByClassName('ulclass')[0];
var button = document.getElementById('submit');
var questionTitle = document.getElementById('question');
//save class name so it can be reused easily
//if I want to change it, I have to change it one place
var classHighlight = 'selected';
// Display Answers and hightlight selected item
//------------------------------------------------------------------
function showQuestions (){
document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
if (currentIndex != 0) {
// create again submit button only for next pages
ulTag.innerHTML ='';
button.innerHTML = 'Submit';
button.className = 'submit';
button.id = 'submit';
if(quizPage<=questions.length){
//update the number of questions displayed
document.getElementById('quizNumber').innerHTML = quizPage;
}
}
//Display Results in the final page
if (currentIndex == (questions.length)) {
ulTag.innerHTML = '';
document.getElementById('question').innerHTML = '';
if(button.id == 'submit'){
button.className = 'buttonload';
button.innerHTML = '<i class="fa fa-spinner fa-spin"></i>Loading';
}
showResults();
return
}
questionTitle.innerHTML = "Question No:" + quizPage + " "+currentQuestion.question.category_name +"<br/>"+ currentQuestion.question.text;
if(currentQuestion.question.filename !== ''){
var br = document.createElement('br');
questionTitle .appendChild(br);
var img = document.createElement('img');
img.src = currentQuestion.question.filename;
img.className = 'imagecenter';
img.width = 750;
img.height = 350;
questionTitle .appendChild(img);
}
// create a for loop to generate the options and display them in the page
for (var i = 0; i < currentQuestion.options.length; i++) {
// creating options
var newAns = document.createElement('li');
newAns.id = 'ans'+ (i+1);
newAns.className = "notSelected listyle";
var textAns = document.createTextNode(currentQuestion.options[i].optiontext);
newAns.appendChild(textAns);
if(currentQuestion.options[i].file !== ''){
var br = document.createElement('br');
newAns .appendChild(br);
var img1 = document.createElement('img');
img1.src = currentQuestion.options[i].file;
img1.className = 'optionimg';
img1.width = 250;
img1.height = 250;
newAns .appendChild(img1);
newAns .appendChild(br);
}
var addNewAnsHere = document.getElementById('options');
addNewAnsHere.appendChild(newAns);
}
//.click() will return the result of $('.notSelected')
var $liTags = $('.notSelected').click(function(list) {
list.preventDefault();
//run removeClass on every element
//if the elements are not static, you might want to rerun $('.notSelected')
//instead of the saved $litTags
$liTags.removeClass(classHighlight);
//add the class to the currently clicked element (this)
$(this).addClass(classHighlight);
//get id name of clicked answer
for (var i = 0; i < currentQuestion.options.length ; i++) {
// console.log(liTagsid[i]);
if($liTags[i].className == "notSelected listyle selected"){
//store information to check answer
tags = $liTags[i].id;
// tagsClass = $LiTags.className;
tagsClassName = $liTags[i];
}
}
});
//check answer once it has been submitted
button.onclick = function (){
if(button.id == 'submit'){
button.className = 'buttonload';
button.innerHTML = '<i class="fa fa-spinner fa-spin"></i>Loading';
}
setTimeout(function() { checkAnswer(); }, 100);
};
}
//self calling function
showQuestions();
The website is on my local now but i can upload a screenimage if need be and the whole code of the webpage. Or is the issue in html?
edit: here is html/css code
<style>
/*========================================================
Quiz Section
========================================================*/
/*styling quiz area*/
.main {
background-color: white;
margin: 0 auto;
margin-top: 30px;
padding: 30px;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
/*white-space: nowrap;*/
}
/*Editing the number of questions*/
.spanclass {
font-size: x-large;
}
#pages{
border: 3px solid;
display: inline-flex;
border-radius: 0.5em;
float: right;
}
#question{
word-break: break-all;
}
/*format text*/
p {
text-align: left;
font-size: x-large;
padding: 10px 10px 0;
}
.optionimg{
border: 2px solid black;
border-radius: 1.5em;
}
/*Form area width*/
/*formatting answers*/
.listyle {
list-style-type: none;
text-align: left;
background-color: transparent;
margin: 10px 5px;
padding: 5px 10px;
border: 1px solid lightgray;
border-radius: 0.5em;
font-weight: normal;
font-size: x-large;
display: inline-grid;
width: 48%;
height: 300px;
overflow: auto;
}
.listyle:hover {
background: #ECEEF0;
cursor: pointer;
}
/*Change effect of question when the questions is selected*/
.selected, .selected:hover {
background: #FFDEAD;
}
/*change correct answer background*/
.correct, .correct:hover {
background: #9ACD32;
color: white;
}
/*change wrong answer background*/
.wrong, .wrong:hover {
background: #db3c3c;
color: white;
}
/*========================================================
Submit Button
========================================================*/
.main button {
text-transform: uppercase;
width: 20%;
border: none;
padding: 15px;
color: #FFFFFF;
}
.submit:hover, .submit:active, .submit:focus {
background: #43A047;
}
.submit {
background: #4CAF50;
min-width: 120px;
}
/*next question button*/
.next {
background: #fa994a;
min-width: 120px;
}
.next:hover, .next:active, .next:focus {
background: #e38a42;
}
.restart {
background-color:
}
/*========================================================
Results
========================================================*/
.circle{
position: relative;
margin: 0 auto;
width: 200px;
height: 200px;
background: #bdc3c7;
-webkit-border-radius: 100px;
-moz-border-radius: 100px;
border-radius: 100px;
overflow: hidden;
}
.fill{
position: absolute;
bottom: 0;
width: 100%;
height: 80%;
background: #31a2ac;
}
.score {
position: absolute;
width: 100%;
top: 1.7em;
text-align: center;
font-family: Arial, sans-serif;
color: #fff;
font-size: 40pt;
line-height: 0;
font-weight: normal;
}
.circle p {
margin: 400px;
}
/*========================================================
Confeeti Effect
========================================================*/
canvas{
position:absolute;
left:0;
top:11em;
z-index:0;
border:0px solid #000;
}
.imagecenter{
display: block;
margin: 0 auto;
}
.buttonload {
background-color: #04AA6D; /* Green background */
border: none; /* Remove borders */
color: white; /* White text */
padding: 12px 24px; /* Some padding */
font-size: 16px; /* Set a font-size */
}
/* Add a right margin to each icon */
.fa {
margin-left: -12px;
margin-right: 8px;
}
#media only screen and (max-width: 900px){
.listyle {
width: 100% !important;
height: auto !important;
}
.imagecenter {
width: 100% !important;
}
.listyle img{
width: inherit !important;
height: unset !important;
}
.ulclass
{
padding:0px !important;
}
}
</style>
<!-- Main page -->
<div class="main">
<!-- Number of Question -->
<div class="wrapper" id="pages">
<span class="spanclass" id="quizNumber">1</span><span class="spanclass">/<?=$count?></span>
</div>
<!-- Quiz Question -->
<div class="quiz-questions" id="display-area">
<p id="question"></p>
<ul class="ulclass" id="options">
</ul>
<div id="quiz-results" class="text-center">
<button type="button" name="button" class="submit" id="submit">Submit</button>
</div>
</div>
</div>
<canvas id="canvas"></canvas>
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
I'm guessing that #question{ word-break: break-all; } is probably the culprit then? –
CB..yes that fixed it:)

First click is not working in javascript for manipulating DOM elements

I am working on one JavaScript project, where I need to toggle between Dark and Light mode.
The HTML is here.
var btnToggle = document.getElementById("btn-toggle")
var btnToggleIcon = document.getElementById("btn-toggle-icon")
var isDark = true;
btnToggleIcon.addEventListener("click", () => {
if (isDark) {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-start";
isDark = false;
document.documentElement.style.setProperty('--color1', '#10111f');
document.documentElement.style.setProperty('--bg1', 'linear-gradient(145deg, #111221, #0e0f1c)');
document.documentElement.style.setProperty('--color5', '#f1f1f3');
document.documentElement.style.setProperty('--bs', '9px 9px 23px #0f111a, -9px -9px 20px #1a1b32');
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
} else {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-end";
isDark = true;
document.documentElement.style.setProperty('--color1', '#f1f1f3');
document.documentElement.style.setProperty('--bg1', '#f1f1f3');
document.documentElement.style.setProperty('--color5', '#10111f');
document.documentElement.style.setProperty('--bs', '20px 20px 60px #bebebe,20px 20px 60px #ffffff');
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
}
})
:root {
--color1: #10111f;
--color2: #6c6c76;
--color3: #265385;
--color4: #6bc3ff;
--color5: #f1f1f3;
--bg1: linear-gradient(145deg, #111221, #0e0f1c);
--bs: 9px 9px 23px #0f111a, -9px -9px 23px #1a1b32;
}
.keyboard {
width: 80vw;
height: 52vh;
background-color: var(--color1);
position: absolute;
left: 10vw;
right: 10vw;
bottom: 5%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 10px;
}
.btn {
color: var(--color5);
font-size: 1.3rem;
cursor: pointer;
border-radius: 8px;
background: var(--bg1);
box-shadow: var(--bs);
padding: 1rem 1.8rem;
transition: all 0.2s ease;
}
<div class="btn-toggle" id="btn-toggle">
<div class="btn-toggle-icon" id="btn-toggle-icon">
<img id="toggle-img" src="https://img.icons8.com/ios/2x/moon-man.png" alt="" />
</div>
</div>
When I click first time on icon but nothing gets changed. But after first click on every click code's running perfectly well.
So please solve this error.
you misinterpret the state, your if(isDark) check the previous state.
i.e. if isDark == true then you should change icon to sun
var btnToggle = document.getElementById("btn-toggle")
var btnToggleIcon = document.getElementById("btn-toggle-icon")
var isDark = true;
btnToggleIcon.addEventListener("click", () => {
if (isDark) {
isDark = false;
//at this point it's not dark
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
} else {
isDark = true;
//at this point it's dark
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
}
})
<div class="btn-toggle" id="btn-toggle">
<div class="btn-toggle-icon" id="btn-toggle-icon">
<img id="toggle-img" src="https://img.icons8.com/ios/2x/moon-man.png" alt="" />
</div>
</div>
Your logic is wrong.
You need to change the variable before the check.
btnToggleIcon.addEventListener("click", () => {
isDark = !isDark;
if (isDark) {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-start";
document.documentElement.style.setProperty('--color1', '#10111f');
document.documentElement.style.setProperty('--bg1', 'linear-gradient(145deg, #111221, #0e0f1c)');
document.documentElement.style.setProperty('--color5', '#f1f1f3');
document.documentElement.style.setProperty('--bs', '9px 9px 23px #0f111a, -9px -9px 20px #1a1b32');
document.getElementById("toggle-img").src = "https://img.icons8.com/ios/2x/moon-man.png"
} else {
console.log(btnToggle.style)
btnToggle.style.justifyContent = "flex-end";
document.documentElement.style.setProperty('--color1', '#f1f1f3');
document.documentElement.style.setProperty('--bg1', '#f1f1f3');
document.documentElement.style.setProperty('--color5', '#10111f');
document.documentElement.style.setProperty('--bs', '20px 20px 60px #bebebe,20px 20px 60px #ffffff');
document.getElementById("toggle-img").src = "https://img.icons8.com/fluent-systems-regular/2x/sun.png"
}
})

Custom Media player design to scale when width changed

I am having a Trouble with this custom media player, Media player not functioning properly.
I have 2 problems:
When full-screen it goes back to the default HTML5 player
When i adjust the width of the video tag it throws all of the spacing out and ruins the player.
HTML
<!DOCTYPE HTML>
<html>
<head>
<title>Video/Audio</title>
<link rel='stylesheet' type='text/css' href='style.css' />
<style type="text/css">
</style>
<script src='jquery.js'></script>
<script src='javascript.js'></script>
<script type='text/javascript'>
$(document).ready(function() {
$('video').videoPlayer({
'playerWidth' : 1,
'videoClass' : 'video'
});
});
</script>
</head>
<body>
<div class="container" class="player">
<video width="700" height="400">
<source src="https://s3-eu-west-1.amazonaws.com/icevideos/151014+Cathodic+Protection+of+Highways/151014.PETERBOROUGH.CATHODICPROTECTION.HIGH1.mp4" type="video/mp4">
<source src="movie.webm" type="video/webm">
</video>
</div>
</body>
</html>
CSS
body {
font-size: 62.5%;
padding: 0;
margin: 0;
}
.player {
background: grey;
box-sizing: border-box;
height: 40px;
-moz-box-sizing: border-box;
float: left;
font-family: Arial, sans-serif;
position: absolute;
padding: 0;
bottom: 4px;
z-index: 2;
opacity: 1;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
-webkit-transition: opacity 0.3s ease-in;
transition: opacity 0.3s ease-in;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
width: 100%;
}
.video {
position: relative;
margin: 0px auto;
}
.video:hover .player {
opacity: 1;
}
.player .progress {
width: 60%;
height: 20px;
border-radius: 5px;
background: #000;
box-shadow: inset 0 -5px 10px rgba(0,0,0,0.1);
float: left;
cursor: pointer;
margin: 12px 0 0 0;
padding: 0;
position: relative;
font-variant: normal;
margin-left: 20px;
}
.player .progress-bar {
background: #FF6600;
border-radius: 5px;
height: 100%;
position: relative;
z-index: 999;
width: 0;
}
.player .button-holder {
position: relative;
left: 10px;
}
.player .progress-button {
background: #00bdff;
box-shadow: 0 0 20px rgba(0,0,0,0.3);
border-radius: 30px;
width: 20px;
height: 20px;
position: absolute;
left: -20px;
text-decoration: overline;
}
.player [class^="buffered"] {
background: rgba(255,255,255,0.1);
position: absolute;
top: 0;
left: 30px;
height: 100%;
border-radius: 5px;
z-index: 1;
}
.player .play-pause {
display: inline-block;
font-size: 3em;
float: left;
text-shadow: 0 0 0 #fff;
color: #00bdff;
width: 4%;
padding: 4px 0 0 0;
margin-left: 15px;
cursor: pointer;
font-variant: small-caps;
}
.player .play, .player .pause-button {
-webkit-transition: all 0.2s ease-out;
}
.player .play .pause-button, .player .pause .play-button {
display: none;
}
.player .pause-button {
padding: 5px 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 34px;
}
.player .pause-button span {
background: #FF6600;
width: 8px;
height: 24px;
float: left;
display: block;
}
.player .pause-button span:first-of-type {
margin: 0 4px 0 0;
}
.player .time {
color: #fff;
font-weight: bold;
font-size: 1.2em;
position: absolute;
width: 150px;
margin-left: 425px;
bottom: 3px;
}
.player .stime, .ttime {
color: #fff;
}
.player .play:hover {
text-shadow: 0 0 5px #fff;
}
.player .play:active, .pause-button:active span {
text-shadow: 0 0 7px #fff;
}
.player .pause-button:hover span {
box-shadow: 0 0 5px #fff;
} .player .pause-button:active span {
box-shadow: 0 0 7px #fff;
}
.player .volume {
position: relative;
float: left;
width: 7%;
height: 100%;
margin-left: 70px;
}
.player .volume-icon {
padding: 1.5%;
height: 100%;
cursor: pointer;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-transition: all 0.15s linear;
}
.player .volume-icon-hover {
background-color: grey;
}
.player .volume-holder {
height: 100px;
width: 80%;
position: absolute;
display: none;
background: grey;
left: 0;
border-radius: 5px 5px 0 0;
top: -100px;
}
.player .volume-bar-holder {
background: black;
width: 20px;
box-shadow: inset 0px 0px 5px rgba(0,0,0,0.3);
margin: 15px auto;
height: 80px;
border-radius: 5px;
position: relative;
cursor: pointer;
}
.player .volume-button {
background: #00bdff;
box-shadow: 0 0 20px rgba(0,0,0,0.3);
border-radius: 30px;
width: 20px;
height: 20px;
}
.player .volume-button-holder {
position: relative;
top: -10px;
}
.player .volume-bar {
background: #FF6600;
border-radius: 5px;
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
}
.player .fullscreen {
width: 5%;
cursor: pointer;
float: left;
height: 100%;
}
.player .fullscreen a {
width: 25px;
height: 20px;
border-radius: 3px;
background: #00bdff;
display: block;
position: relative;
top: 10px;
margin: 0px auto;
}
.player .fullscreen a:hover {
background: #FF6600;
}
.player .volume-icon span {
width: 20%;
height: 23%;
background-color: #00bdff;
display: block;
position: relative;
z-index: 1;
font-weight: bold;
top: 40%;
color: #fff;
left: 22%;
}
.player .volume-icon span:before,
.player .volume-icon span:after {
content: '';
position: absolute;
}
.player .volume-icon span:before {
width: 0;
height: 0;
border: 1em solid transparent;
border-left: none;
border-right-color: #00bdff;
z-index: 2;
top: -2px;
left: 10%;
margin-top: -40%;
}
.player .volume-icon span:after {
width: 10%;
height: 4%;
border: 1px solid #00bdff;
left: 150%;
border-width: 0px 0px 0 0;
border-radius: 0 50px 0 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
font-variant: small-caps;
}
.player .v-change-11 span:after { border-width: 10px 10px 0 0; top: 0; }
.player .v-change-10 span:after { border-width: 9px 9px 0 0; top: 1px; }
.player .v-change-9 span:after { border-width: 8px 8px 0 0; top: 1px; }
.player .v-change-8 span:after { border-width: 7px 7px 0 0; top: 2px; }
.player .v-change-7 span:after { border-width: 6px 6px 0 0; top: 2px; }
.player .v-change-6 span:after { border-width: 5px 5px 0 0; top: 3px; }
.player .v-change-5 span:after { border-width: 4px 4px 0 0; top: 3px; }
.player .v-change-4 span:after { border-width: 3px 3px 0 0; top: 4px; }
.player .v-change-3 span:after { border-width: 2px 2px 0 0; top: 4px; }
.player .v-change-2 span:after { border-width: 1px 1px 0 0; top: 5px; }
.player .v-change-1 span:after { border-width: 0px 0px 0 0; top: 5px; }
.player .v-change-1 span:after {
content: '+';
-webkit-transform: rotate(45deg);
font-size: 20px;
top: -6px;
left: 25px;
color: #00bdff;
}
/* ------- IGNORE */
#header {
width: 100%;
margin: 0px auto;
}
#header #center {
text-align: center;
}
#header h1 span {
color: #000;
display: block;
font-size: 50px;
}
#header p {
font-family: 'Georgia', serif;
}
#header h1 {
color: #892dbf;
font: bold 40px 'Bree Serif', serif;
}
#travel {
padding: 10px;
background: rgba(0,0,0,0.6);
border-bottom: 2px solid rgba(0,0,0,0.2);
font-variant: normal;
text-decoration: none;
}
#travel a {
font-family: 'Georgia', serif;
text-decoration: none;
border-bottom: 1px solid #f9f9f9;
font-size: 20px;
color: #f9f9f9;
}
.container {
padding: 40px 0 0 0;
}
.logo {
margin-top: 9px;
float: left;
margin-left: 6px;
}
JS
(function($) {
$.fn.videoPlayer = function(options) {
var settings = {
playerWidth : '0.95', // Default is 95%
videoClass : 'video' // Video Class
}
// Extend the options so they work with the plugin
if(options) {
$.extend(settings, options);
}
// For each so that we keep chainability.
return this.each(function() {
$(this)[0].addEventListener('loadedmetadata', function() {
// Basic Variables
var $this = $(this);
var $settings = settings;
// Wrap the video in a div with the class of your choosing
$this.wrap('<div class="'+$settings.videoClass+'"></div>');
// Select the div we just wrapped our video in for easy selection.
var $that = $this.parent('.'+$settings.videoClass);
// The Structure of our video player
{
$( '<div class="player">'
+'<img class="logo" src="http://www.cpdonline.tv/ice-events/mediaplayer/icelogo.png" height="20px">'
+ '<div class="play-pause play">'
+ '<span class="play-button">►</span>'
+ '<div class="pause-button">'
+ '<span> </span>'
+ '<span> </span>'
+ '</div>'
+ '</div>'
+ '<div class="progress">'
+ '<div class="progress-bar">'
+ '<div class="button-holder">'
+ '<div class="progress-button"> </div>'
+ '</div>'
+ '</div>'
+ '<div class="time">'
+ '<span class="ctime">00:00</span>'
+ '<span class="stime"> / </span>'
+ '<span class="ttime">00:00</span>'
+ '</div>'
+ '</div>'
+ '<div class="volume">'
+ '<div class="volume-holder">'
+ '<div class="volume-bar-holder">'
+ '<div class="volume-bar">'
+ '<div class="volume-button-holder">'
+ '<div class="volume-button"> </div>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '</div>'
+ '<div class="volume-icon v-change-0">'
+ '<span> </span>'
+ '</div>'
+ '</div>'
+ '<div class="fullscreen"> '
+ ' '
+ '</div>'
+ '</div>').appendTo($that);
}
// Width of the video
$videoWidth = $this.width();
$that.width($videoWidth+'px');
// Set width of the player based on previously noted settings
$that.find('.player').css({'width' : ($settings.playerWidth*100)+'%', 'left' : ((100-$settings.playerWidth*100)/2)+'%'});
// Video information
var $spc = $(this)[0], // Specific video
$duration = $spc.duration, // Video Duration
$volume = $spc.volume, // Video volume
currentTime;
// Some other misc variables to check when things are happening
var $mclicking = false,
$vclicking = false,
$vidhover = false,
$volhover = false,
$playing = false,
$drop = false,
$begin = false,
$draggingProgess = false,
$storevol,
x = 0,
y = 0,
vtime = 0,
updProgWidth = 0,
volume = 0;
// Setting the width, etc of the player
var $volume = $spc.volume;
// So the user cant select text in the player
$that.bind('selectstart', function() { return false; });
// Set some widths
var progWidth = $that.find('.progress').width();
var bufferLength = function() {
// The buffered regions of the video
var buffered = $spc.buffered;
// Rest all buffered regions everytime this function is run
$that.find('[class^=buffered]').remove();
// If buffered regions exist
if(buffered.length > 0) {
// The length of the buffered regions is i
var i = buffered.length;
while(i--) {
// Max and min buffers
$maxBuffer = buffered.end(i);
$minBuffer = buffered.start(i);
// The offset and width of buffered area
var bufferOffset = ($minBuffer / $duration) * 100;
var bufferWidth = (($maxBuffer - $minBuffer) / $duration) * 100;
// Append the buffered regions to the video
$('<div class="buffered"></div>').css({"left" : bufferOffset+'%', 'width' : bufferWidth+'%'}).appendTo($that.find('.progress'));
}
}
}
// Run the buffer function
bufferLength();
// The timing function, updates the time.
var timeUpdate = function($ignore) {
// The current time of the video based on progress bar position
var time = Math.round(($('.progress-bar').width() / progWidth) * $duration);
// The 'real' time of the video
var curTime = $spc.currentTime;
// Seconds are set to 0 by default, minutes are the time divided by 60
// tminutes and tseconds are the total mins and seconds.
var seconds = 0,
minutes = Math.floor(time / 60),
tminutes = Math.round($duration / 60),
tseconds = Math.round(($duration) - (tminutes*60));
// If time exists (well, video time)
if(time) {
// seconds are equal to the time minus the minutes
seconds = Math.round(time) - (60*minutes);
// So if seconds go above 59
if(seconds > 59) {
// Increase minutes, reset seconds
seconds = Math.round(time) - (60*minutes);
if(seconds == 60) {
minutes = Math.round(time / 60);
seconds = 0;
}
}
}
// Updated progress width
updProgWidth = (curTime / $duration) * progWidth
// Set a zero before the number if its less than 10.
if(seconds < 10) { seconds = '0'+seconds; }
if(tseconds < 10) { tseconds = '0'+tseconds; }
// A variable set which we'll use later on
if($ignore != true) {
$that.find('.progress-bar').css({'width' : updProgWidth+'px'});
$that.find('.progress-button').css({'left' : (updProgWidth-$that.find('.progress-button').width())+'px'});
}
// Update times
$that.find('.ctime').html(minutes+':'+seconds)
$that.find('.ttime').html(tminutes+':'+tseconds);
// If playing update buffer value
if($spc.currentTime > 0 && $spc.paused == false && $spc.ended == false) {
bufferLength();
}
}
// Run the timing function twice, once on init and again when the time updates.
timeUpdate();
$spc.addEventListener('timeupdate', timeUpdate);
// When the user clicks play, bind a click event
$that.find('.play-pause').bind('click', function() {
// Set up a playing variable
if($spc.currentTime > 0 && $spc.paused == false && $spc.ended == false) {
$playing = false;
} else { $playing = true; }
// If playing, etc, change classes to show pause or play button
if($playing == false) {
$spc.pause();
$(this).addClass('play').removeClass('pause');
bufferLength();
} else {
$begin = true;
$spc.play();
$(this).addClass('pause').removeClass('play');
}
});
// Bind a function to the progress bar so the user can select a point in the video
$that.find('.progress').bind('mousedown', function(e) {
// Progress bar is being clicked
$mclicking = true;
// If video is playing then pause while we change time of the video
if($playing == true) {
$spc.pause();
}
// The x position of the mouse in the progress bar
x = e.pageX - $that.find('.progress').offset().left;
// Update current time
currentTime = (x / progWidth) * $duration;
$spc.currentTime = currentTime;
});
// When the user clicks on the volume bar holder, initiate the volume change event
$that.find('.volume-bar-holder').bind('mousedown', function(e) {
// Clicking of volume is true
$vclicking = true;
// Y position of mouse in volume slider
y = $that.find('.volume-bar-holder').height() - (e.pageY - $that.find('.volume-bar-holder').offset().top);
// Return false if user tries to click outside volume area
if(y < 0 || y > $(this).height()) {
$vclicking = false;
return false;
}
// Update CSS to reflect what's happened
$that.find('.volume-bar').css({'height' : y+'px'});
$that.find('.volume-button').css({'top' : (y-($that.find('.volume-button').height()/2))+'px'});
// Update some variables
$spc.volume = $that.find('.volume-bar').height() / $(this).height();
$storevol = $that.find('.volume-bar').height() / $(this).height();
$volume = $that.find('.volume-bar').height() / $(this).height();
// Run a little animation for the volume icon.
volanim();
});
// A quick function for binding the animation of the volume icon
var volanim = function() {
// Check where volume is and update class depending on that.
for(var i = 0; i < 1; i += 0.1) {
var fi = parseInt(Math.floor(i*10)) / 10;
var volid = (fi * 10)+1;
if($volume == 1) {
if($volhover == true) {
$that.find('.volume-icon').removeClass().addClass('volume-icon volume-icon-hover v-change-11');
} else {
$that.find('.volume-icon').removeClass().addClass('volume-icon v-change-11');
}
}
else if($volume == 0) {
if($volhover == true) {
$that.find('.volume-icon').removeClass().addClass('volume-icon volume-icon-hover v-change-1');
} else {
$that.find('.volume-icon').removeClass().addClass('volume-icon v-change-1');
}
}
else if($volume > (fi-0.1) && volume < fi && !$that.find('.volume-icon').hasClass('v-change-'+volid)) {
if($volhover == true) {
$that.find('.volume-icon').removeClass().addClass('volume-icon volume-icon-hover v-change-'+volid);
} else {
$that.find('.volume-icon').removeClass().addClass('volume-icon v-change-'+volid);
}
}
}
}
// Run the volanim function
volanim();
// Check if the user is hovering over the volume button
$that.find('.volume').hover(function() {
$volhover = true;
}, function() {
$volhover = false;
});
// For usability purposes then bind a function to the body assuming that the user has clicked mouse
// down on the progress bar or volume bar
$('body, html').bind('mousemove', function(e) {
// Hide the player if video has been played and user hovers away from video
if($begin == true) {
$that.hover(function() {
$that.find('.player').stop(true, false).animate({'opacity' : '1'}, 0.5);
}, function() {
$that.find('.player').stop(true, false).animate({'opacity' : '0'}, 0.5);
});
}
// For the progress bar controls
if($mclicking == true) {
// Dragging is happening
$draggingProgress = true;
// The thing we're going to apply to the CSS (changes based on conditional statements);
var progMove = 0;
// Width of the progress button (a little button at the end of the progress bar)
var buttonWidth = $that.find('.progress-button').width();
// Updated x posititon the user is at
x = e.pageX - $that.find('.progress').offset().left;
// If video is playing
if($playing == true) {
// And the current time is less than the duration
if(currentTime < $duration) {
// Then the play-pause icon should definitely be a pause button
$that.find('.play-pause').addClass('pause').removeClass('play');
}
}
if(x < 0) { // If x is less than 0 then move the progress bar 0px
progMove = 0;
$spc.currentTime = 0;
}
else if(x > progWidth) { // If x is more than the progress bar width then set progMove to progWidth
$spc.currentTime = $duration;
progMove = progWidth;
}
else { // Otherwise progMove is equal to the mouse x coordinate
progMove = x;
currentTime = (x / progWidth) * $duration;
$spc.currentTime = currentTime;
}
// Change CSS based on previous conditional statement
$that.find('.progress-bar').css({'width' : $progMove+'px'});
$that.find('.progress-button').css({'left' : ($progMove-buttonWidth)+'px'});
}
// For the volume controls
if($vclicking == true) {
// The position of the mouse on the volume slider
y = $that.find('.volume-bar-holder').height() - (e.pageY - $that.find('.volume-bar-holder').offset().top);
// The position the user is moving to on the slider.
var volMove = 0;
// If the volume holder box is hidden then just return false
if($that.find('.volume-holder').css('display') == 'none') {
$vclicking = false;
return false;
}
// Add the hover class to the volume icon
if(!$that.find('.volume-icon').hasClass('volume-icon-hover')) {
$that.find('.volume-icon').addClass('volume-icon-hover');
}
if(y < 0 || y == 0) { // If y is less than 0 or equal to 0 then volMove is 0.
$volume = 0;
volMove = 0;
$that.find('.volume-icon').removeClass().addClass('volume-icon volume-icon-hover v-change-11');
} else if(y > $(this).find('.volume-bar-holder').height() || (y / $that.find('.volume-bar-holder').height()) == 1) { // If y is more than the height then volMove is equal to the height
$volume = 1;
volMove = $that.find('.volume-bar-holder').height();
$that.find('.volume-icon').removeClass().addClass('volume-icon volume-icon-hover v-change-1');
} else { // Otherwise volMove is just y
$volume = $that.find('.volume-bar').height() / $that.find('.volume-bar-holder').height();
volMove = y;
}
// Adjust the CSS based on the previous conditional statmeent
$that.find('.volume-bar').css({'height' : volMove+'px'});
$that.find('.volume-button').css({'top' : (volMove+$that.find('.volume-button').height())+'px'});
// Run the animation function
volanim();
// Change the volume and store volume
// Store volume is the volume the user last had in place
// in case they want to mute the video, unmuting will then
// return the user to their previous volume.
$spc.volume = $volume;
$storevol = $volume;
}
// If the user hovers over the volume controls, then fade in or out the volume
// icon hover class
if($volhover == false) {
$that.find('.volume-holder').stop(true, false).fadeOut(100);
$that.find('.volume-icon').removeClass('volume-icon-hover');
}
else {
$that.find('.volume-icon').addClass('volume-icon-hover');
$that.find('.volume-holder').fadeIn(100);
}
})
// When the video ends the play button becomes a pause button
$spc.addEventListener('ended', function() {
$playing = false;
// If the user is not dragging
if($draggingProgress == false) {
$that.find('.play-pause').addClass('play').removeClass('pause');
}
});
// If the user clicks on the volume icon, mute the video, store previous volume, and then
// show previous volume should they click on it again.
$that.find('.volume-icon').bind('mousedown', function() {
$volume = $spc.volume; // Update volume
// If volume is undefined then the store volume is the current volume
if(typeof $storevol == 'undefined') {
$storevol = $spc.volume;
}
// If volume is more than 0
if($volume > 0) {
// then the user wants to mute the video, so volume will become 0
$spc.volume = 0;
$volume = 0;
$that.find('.volume-bar').css({'height' : '0'});
volanim();
}
else {
// Otherwise user is unmuting video, so volume is now store volume.
$spc.volume = $storevol;
$volume = $storevol;
$that.find('.volume-bar').css({'height' : ($storevol*100)+'%'});
volanim();
}
});
// If the user lets go of the mouse, clicking is false for both volume and progress.
// Also the video will begin playing if it was playing before the drag process began.
// We're also running the bufferLength function
$('body, html').bind('mouseup', function(e) {
$mclicking = false;
$vclicking = false;
$draggingProgress = false;
if($playing == true) {
$spc.play();
}
bufferLength();
});
// Check if fullscreen supported. If it's not just don't show the fullscreen icon.
if(!$spc.requestFullscreen && !$spc.mozRequestFullScreen && !$spc.webkitRequestFullScreen) {
$('.fullscreen').hide();
}
// Requests fullscreen based on browser.
$('.fullscreen').click(function() {
if ($spc.requestFullscreen) {
$spc.requestFullscreen();
}
else if ($spc.mozRequestFullScreen) {
$spc.mozRequestFullScreen();
}
else if ($spc.webkitRequestFullScreen) {
$spc.webkitRequestFullScreen();
}
});
});
});
}
})(jQuery);
I would also like to point out that this is someone else source code and cannot find where i got this from.
https://jsfiddle.net/f39huqpv/

Web audio oscillator is clicking in Firefox only

I'm trying to create a simple metronome using the web audio oscillator, so that no external audio files are needed. I'm creating the sound of the metronome by ramping the volume of the oscillator up and down very quickly (since you can't use start() and stop() more than once), and then repeating that function at a set interval. It ends up sounding like a nice little wood block.
The code below works/sounds great in Chrome, Safari and Opera. But in Firefox, there's a nasty intermittent "click" when the volume ramps up. I've tried changing the attack/release times to get rid of the click, but they have to be really, really long before it consistently disappears. So long, in fact, that the oscillator just sounds like a sustained note.
var audio = new (window.AudioContext || window.webkitAudioContext)();
var tick = audio.createOscillator();
var tickVol = audio.createGain();
tick.type = 'sine';
tick.frequency.value = 1000;
tickVol.gain.value = 0; //setting the volume to 0 before I connect everything
tick.connect(tickVol);
tickVol.connect(audio.destination);
tick.start(0);
var metronome = {
start: function repeat() {
now = audio.currentTime;
//Make sure volume is 0 and that no events are changing it
tickVol.gain.cancelScheduledValues(now);
tickVol.gain.setValueAtTime(0, now);
//Play the osc with a super fast attack and release so it sounds like a click
tickVol.gain.linearRampToValueAtTime(1, now + .001);
tickVol.gain.linearRampToValueAtTime(0, now + .001 + .01);
//Repeat this function every half second
click = setTimeout(repeat, 500);
},
stop: function() {
if(typeof click !== 'undefined') {
clearTimeout(click);
tickVol.gain.value = 0;
}
}
}
$("#start").click(function(){
metronome.start();
});
$("#stop").click(function(){
metronome.stop();
});
Codepen
Is there any way to get FF to sound like the other 3 browsers?
I was getting the exact same problem in latest Opera and found the problem to be the individual sounds 'decimal time length'.
I wrote a morse code translator, and like yours, it's just a series of simple short sounds/beeps created via createOscillator.
With morse code you have a speed count (words per minute) based on a 5 letter long word like codex or paris.
To get 20 or 30 paris' per minute to finish exactly on the minute, I had to use a sound time length of, for example, 0.61. In Opera, this caused the 'end of sound click'. On changing this to 0.6 and the click disappeared across all browsers - except Firefox.
I've tried freq = 0 and gain = 0 between sounds but still get the click at the end in FF and I don't know enough about Web Audio to try anything else.
On another note, I noticed you're using a loop and timeout to get to the next tick. Have you tried an 'Oscillator onended function' instead? I've used it with a simple counter increment and variable length blank sound/note. Go to the very end of my JS if you want to have a look.
**UPDATE - I've been fiddling about with setValueAtTime() and linearRampToValueAtTime() and appeared to have cracked the click problem. Scroll to bottom of script to see example. **
(function(){
/* Morse Code Generator & Translator - Kurt Grigg 2003 (Updated for sound and CSS3) */
var d = document;
d.write('<div class="Mcontainer">'
+'<div class="Mtitle">Morse Code Generator Translator</div>'
+'<textarea id="txt_in" class="Mtxtarea"></textarea>'
+'<div class="Mtxtareatitle">Input</div>'
+'<textarea id="txt_out" class="Mtxtarea" style="top: 131px;"></textarea>'
+'<div class="Mtxtareatitle" style="top: 172px;">Output</div>'
+'<div class="Mbuttonwrap">'
+'<input type="button" class="Mbuttons" id="how" value="!">'
+'<input type="button" class="Mbuttons" id="tra" value="translate">'
+'<input type="button" class="Mbuttons" id="ply" value="play">'
+'<input type="button" class="Mbuttons" id="pau" value="pause">'
+'<input type="button" class="Mbuttons" id="res" value="reset"></div>'
+'<select id="select" class="Mselect">'
+'<option value=0.07 selected="selected">15 wpm</option>'
+'<option value=0.05>20 wpm</option>'
+'<option value=0.03>30 wpm</option>'
+'</select>'
+'<div class="sliderWrap">volume <input id="volume" type="range" min="0" max="1" step="0.01" value="0.05"/></div>'
+'<div class="Mchckboxwrap">'
+'<span style="text-align: right;">separator <input type="checkbox" id="slash" class="Mchckbox"></span>'
+'</div>'
+'<div id="about" class="Minfo">'
+'<b>Input morse</b><br>'
+'<ul><li>Enter morse into input box using full stop (period) and minus sign (hyphen)</li>'
+'<li>Morse letters must be separated by 1 space</li>'
+'<li>Morse words must be separated by 3 or more spaces</li>'
+'<li>You can use / to separate morse words. There must be at least 1 space before and after each separator used</li>'
+'</ul>'
+'<b>Input text</b><br>'
+'<ul class="Mul"><li>Enter text into input box</li>'
+'<li>Characters that cannot be translated will be ignored</li>'
+'<li>If morse and text is entered, the converter will assume morse mode</li></ul>'
+'<input type="button" value="close" id="clo" class="Mbuttons">'
+'</div><div id="mdl" class="modal"><div id="bdy"><div id="modalMsg">A MSG</div><input type="button" value="close" id="cls" class="Mbuttons"></div></div></div>');
var ftmp = d.getElementById('mdl');
var del;
d.getElementById('tra').addEventListener("click", function(){convertToAndFromMorse(txtIn.value);},false);
d.getElementById('ply').addEventListener("click", function(){CancelIfPlaying();},false);
d.getElementById('pau').addEventListener("click", function(){stp();},false);
d.getElementById('res').addEventListener("click", function(){Rst();txtIn.value = '';txtOt.value = '';},false);
d.getElementById('how').addEventListener("click", function(){msgSelect();},false);
d.getElementById('clo').addEventListener("click", function(){fadeOut();},false);
d.getElementById('cls').addEventListener("click", function(){fadeOut();},false);
d.getElementById('bdy').addEventListener("click", function(){errorSelect();},false);
var wpm = d.getElementById('select');
wpm.addEventListener("click", function(){wpMin()},false);
var inc = 0;
var playing = false;
var txtIn = d.getElementById('txt_in');
var txtOt = d.getElementById('txt_out');
var paused = false;
var allowed = ['-','.',' '];
var aud;
var tmp = (window.AudioContext || window.webkitAudioContext)?true:false;
if (tmp) {
aud = new (window.AudioContext || window.webkitAudioContext)();
}
var incr = 0;
var speed = parseFloat(wpm.options[wpm.selectedIndex].value);
var char = [];
var alphabet = [["A",".-"],["B","-..."],["C","-.-."],["D","-.."],["E","."],["F","..-."],["G","--."],["H","...."],["I",".."],["J",".---"],
["K","-.-"],["L",".-.."],["M","--"],["N","-."],["O","---"],["P",".--."],["Q","--.-"],["R",".-."],["S","..."],["T","-"],["U","..-"],
["V","...-"],["W",".--"],["X","-..-"],["Y","-.--"],["Z","--.."],["1",".----"],["2","..---"],["3","...--"],["4","....-"],["5","....."],
["6","-...."],["7","--..."],["8","---.."],["9","----."],["0","-----"],[".",".-.-.-"],[",","--..--"],["?","..--.."],["'",".----."],["!","-.-.--"],
["/","-..-."],[":","---..."],[";","-.-.-."],["=","-...-"],["-","-....-"],["_","..--.-"],["\"",".-..-."],["#",".--.-."],["(","-.--.-"],[" ",""]];
function errorSelect() {
txtIn.focus();
}
function modalSwap(msg) {
d.getElementById('modalMsg').innerHTML = msg;
}
function msgSelect() {
ftmp = d.getElementById('about');
fadeIn();
}
function fadeIn() {
ftmp.removeEventListener("transitionend", freset);
ftmp.style.display = "block";
del = setTimeout(doFadeIn,100);
}
function doFadeIn() {
clearTimeout(del);
ftmp.style.transition = "opacity 0.5s linear";
ftmp.style.opacity = "1";
}
function fadeOut() {
ftmp.style.transition = "opacity 0.8s linear";
ftmp.style.opacity = "0";
ftmp.addEventListener("transitionend",freset , false);
}
function freset() {
ftmp.style.display = "none";
ftmp.style.transition = "";
ftmp = d.getElementById('mdl');
}
function stp() {
paused = true;
}
function wpMin() {
speed = parseFloat(wpm.options[wpm.selectedIndex].value);
}
function Rst(){
char = [];
inc = 0;
playing = false;
paused = false;
}
function CancelIfPlaying(){
if (window.AudioContext || window.webkitAudioContext) {paused = false;
if (!playing) {
IsReadyToHear();
}
else {
return false;
}
}
else {
modalSwap("<p>Your browser doesn't support Web Audio API</p>");
fadeIn();
return false;
}
}
function IsReadyToHear(x){
if (txtIn.value == "" || /^\s+$/.test(txtIn.value)) {
modalSwap('<p>Nothing to play, enter morse or text first</p>');
fadeIn();
txtIn.value = '';
return false;
}
else if (char.length < 1 && (x != "" || !/^\s+$/.test(txtIn.value)) && txtIn.value.length > 0) {
modalSwap('<p>Click Translate button first . . .</p>');
fadeIn();
return false;
}
else{
playMorse();
}
}
function convertToAndFromMorse(x){
var swap = [];
var outPut = "";
x = x.toUpperCase();
/* Is input empty or all whitespace? */
if (x == '' || /^\s+$/.test(x)) {
modalSwap("<p>Nothing to translate, enter morse or text</p>");
fadeIn();
txtIn.value = '';
return false;
}
/* Remove front & end whitespace */
x = x.replace(/\s+$|^\s*/gi, '');
txtIn.value = x;
txtOt.value = "";
var isMorse = (/(\.|\-)\.|(\.|\-)\-/i.test(x));// Good enough.
if (!isMorse){
for (var i = 0; i < alphabet.length; i++){
swap[i] = [];
for (var j = 0; j < 2; j++){
swap[i][j] = alphabet[i][j].replace(/\-/gi, '\\-');
}
}
}
var swtch1 = (isMorse) ? allowed : swap;
var tst = new RegExp( '[^' + swtch1.join('') + ']', 'g' );
var swtch2 = (isMorse)?' ':'';
x = x.replace( tst, swtch2); //remove unwanted chars.
x = x.split(swtch2);
if (isMorse) {
var tidy = [];
for (var i = 0; i < x.length; i++){
if ((x[i] != '') || x[i+1] == '' && x[i+2] != '') {
tidy.push(x[i]);
}
}
}
var swtch3 = (isMorse) ? tidy : x;
for (var j = 0; j < swtch3.length; j++) {
for (var i = 0; i < alphabet.length; i++){
if (isMorse) {
if (tidy[j] == alphabet[i][1]) {
outPut += alphabet[i][0];
}
}
else {
if (x[j] == alphabet[i][0]) {
outPut += alphabet[i][1] + ((j < x.length-1)?" ":"");
}
}
}
}
if (!isMorse) {
var wordDivide = (d.getElementById('slash').checked)?" / ":" ";
outPut = outPut.replace(/\s{3,}/gi, wordDivide);
}
if (outPut.length < 1) {
alert('Enter valid text or morse...');
txtIn.value = '';
}
else {
txtOt.value = outPut;
}
var justMorse = (!isMorse) ? outPut : tidy;
FormatForSound(justMorse);
}
function FormatForSound(s){
var n = [];
var b = '';
if (typeof s == 'object') {
for (var i = 0; i < s.length; ++i) {
var f = (i == s.length-1)?'':' ';
var t = b += (s[i] + f);
}
}
var c = (typeof s == 'object')? t : s;
c = c.replace(/\//gi, '');
c = c.replace(/\s{1,3}/gi, '4');
c = c.replace(/\./gi, '03');
c = c.replace(/\-/gi, '13');
c = c.split('');
for (var i = 0; i < c.length; i++) {
n.push(c[i]);
}
char = n;
}
function vlm() {
return document.getElementById('volume').value;
}
function playMorse() {
if (paused){
playing = false;
return false;
}
playing = true;
if (incr >= char.length) {
incr = 0;
playing = false;
paused = false;
return false;
}
var c = char[incr];
var freq = 550;
var volume = (c < 2) ? vlm() : 0 ;
var flen = (c == 0 || c == 3) ? speed : speed * 3;
var osc = aud.createOscillator();
osc.type = 'sine';
osc.frequency.value = freq;
var oscGain = aud.createGain();
oscGain.gain.value = volume;
osc.connect(oscGain);
oscGain.connect(aud.destination);
var now = aud.currentTime;
osc.start(now);
/*
Sharp volume fade to stop harsh clicks if wave is stopped
at a point other than the (natural zero crossing point)
*/
oscGain.gain.setValueAtTime(volume, now + (flen*0.8));
oscGain.gain.linearRampToValueAtTime(0.0, now + (flen*0.9999));
osc.stop(now + flen);
osc.onended = function() {
incr++;
playMorse();
}
}
})();
body {
text-align: center;
}
.Mcontainer {
display: inline-block;
position: relative;
width: 382px;
height: 302px;
border: 1px solid #000;
border-radius: 6px;
text-align: center;
font: bold 11px sans-serif;
background-color: rgb(203,243,65);
box-shadow: 0px 4px 2px rgba(0,0,0,0.3);
}
.Mtitle {
-webkit-user-select: none;
-moz-user-select: none;
display: inline-block;
position: absolute;
width: 380px;
height: 20px;
margin: auto;
left: 0; right: 0;
font-size: 16px;
line-height: 20px;
color: #666;
}
.Mtxtareatitle {
-webkit-user-select: none;
-moz-user-select: none;
display: block;
position: absolute;
top: 60px;
left: -36px;
height: 22px;
width: 106px;
font-size: 18px;
line-height: 22px;
text-align: center;
color: #555;
transform: rotate(-90deg);
}
.Mtxtarea {
display: block;
position: absolute;
top: 18px;
margin: auto;
left: 0; right: 0;
height: 98px;
width: 344px;
border: 0.5px solid #000;
border-radius: 6px;
padding-top: 6px;
padding-left: 24px;
resize: none;
background-color: #fffff0;
font: bold 10px courier;
color: #555;
text-transform: uppercase;
overflow: auto;
outline: 0; box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5);
}
.Minfo {
display: none;
position: absolute;
top: -6px; left:-6px;
padding: 6px;
height: auto;
width: 370px;
text-align: left;
border: 0.5px solid #000;
border-radius: 6px;
box-shadow: 0px 4px 2px rgba(0,0,0,0.3);
background-color: rgb(203,243,65);
font: 11px sans-serif;
color: #555;
opacity: 0;
}
.Mbuttonwrap {
display: block;
position: absolute;
top: 245px;
margin: auto;
left: 0; right: 0;
height: 26px;
width: 100%;
}
.Mbuttons {
display: inline-block;
width: 69px;
height: 22px;
border: none;
margin: 0px 3.1px 0px 3.1px;
background-color: transparent;
font: bold 11px sans-serif;
color: #555;
border-radius: 20px;
cursor: pointer;
box-shadow: 0px 2px 2px rgba(0,0,0,0.5);
outline: 0;
}
.Mbuttons:hover {
background-color: rgb(213,253,75);
}
.Mbuttons:active {
position: relative;
top: 1px;
box-shadow: 0px 1px 2px rgba(0,0,0,0.8);
}
.Mchckboxwrap {
display: block;
position: absolute;
top: 274px;
left: 289px;
width: 87px;
height: 21px;
line-height: 22px;
border: 0.5px solid #000;
color: #555;
background: #fff;
-webkit-user-select: none;
-moz-user-select: none;
}
.Mselect {
display: block;
position: absolute;
top: 274px;
left: 6px;
width: 88px;
height: 22px;
border: 0.5px solid #000;
padding-left: 5%;
background: #fff;
font: bold 11px sans-serif;
color: #555;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
outline: 0;
}
::selection {
color: #fff;
background: #555;
}
.Mchckbox {
margin-top: 1px;
vertical-align: middle;
cursor: pointer;
outline: 0;
}
.modal {
display: none;
position: absolute;
margin: auto;
top: 0;right: 0;bottom: 0;left: 0;
background: rgba(0,0,0,0.5);
-webkit-user-select: none;
-moz-user-select: none;
opacity: 0;
text-align: center;
}
.modal > div {
display: inline-block;
position: relative;
width: 250px;
height: 70px;
margin: 10% auto;
padding: 10px;
border: 0.5px solid #000;
border-radius:6px;
background-color: rgb(203,243,65);
font: bold 11px sans-serif;
color: #555;
box-shadow: 4px 4px 2px rgba(0,0,0,0.3);
text-align: center;
}
.sliderWrap {
display: block;
position: absolute;
top: 274px;
margin:auto;padding: 0;
left: 0; right: 0;
width: 184px;
height: 21px;
border: 0.5px solid #000;
background: #fff;
font: bold 11px sans-serif;
color: #555;
line-height: 21px;
text-align: center;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
outline: 0;
}
input[type=range] {
-webkit-appearance: none;
width: 50%;
margin: 0;padding: 0;
vertical-align: middle;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: #666;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 1px 1px 0.5px rgba(0, 0, 0, 0.5);
border: none;
height: 10px;
width: 20px;
border-radius: 5px;
background: #ffffff;
cursor: pointer;
-webkit-appearance: none;
margin-top: -3px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #666;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 4px;
cursor: pointer;
background: #666;
}
input[type=range]::-moz-range-thumb {
box-shadow: 1px 1px 0.5px rgba(0, 0, 0, 0.5);
height: 10px;
width: 20px;
border: none;
border-radius: 5px;
background: #ffffff;
cursor: pointer;
}
input[type=range]::-ms-thumb {
height: 10px;
width: 20px;
border: none;
border-radius: 5px;
background: #ffffff;
box-shadow: 1px 1px 0.5px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 4px;
cursor: pointer;
background: transparent;
border: 5px solid transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #666;
}
input[type=range]::-ms-fill-upper {
background: #666;
}
::-ms-tooltip {
display: none;
}
select::-ms-expand {
display: none;
}
It would be best to get Firefox to fix the issue (if indeed it is a Firefox bug with automations). Having said that, you could probably make all the browsers be consistent by using an AudioBufferSource node that has a precomputed click waveform that you want. Just generate a sine wave, ramp it up and down as you want (manually) and play that back at regular intervals.
Not great, but it should be cross-platform.
AFAIK this issue is not specific to Firefox, although looking at your code, I'm unsure why it doesn't happen in other browsers.
The problem is that the moment you schedule a *rampToValueAtTime to an audible source when that source is not currently interpolating between two ramp points, the "clicking" sound occurrs, possibly due to how the underlying implementation will immediately start taking the new ramp point into consideration, even if it's scheduled to happen the future.
The clicking sound will also be heard if you schedule a new ramp point between two points between which interpolation is occurring.
What I came up with as a workaround solution is either using an alternative approach to gradually changing AudioParam values, setTargetAtTime, or setting the value property of the AudioParam to the first ramp point value. Not setValueAtTime, but assigning to the value property itself, before anything audible happens on the given branch.
setTargetAtTime
You'll be needing neither cancelScheduledValues nor setValueAtTime, just two calls to setTargetAtTime, which is just a setValueAtTime with an exponential interpolation with a specified length.
var metronome = {
start: function repeat() {
now = audio.currentTime;
//Play the osc with a super fast attack and release so it sounds like a click
tickVol.gain.setTargetAtTime(1, now, 0.01);
tickVol.gain.setTargetAtTime(0, now + 0.01, 0.01);
//Repeat this function every half second
click = setTimeout(repeat, 500);
}
}
Live demo on JSFiddle

Floating Button doesn't change background image on click

I'm creating my first custom audio player - i'm pretty new to WebDesign -
I have my Play button shown when the page loads
When i click the playbtn it dissapears, the track plays, i can stop it by clicking on the same spot where the playbtn was before, and the track stops but still no picture,
so my audio simply doesnt load the backgroungImage of my Javascript code! even that the rest of the code works!
JavaScript
// vars
var my_track, playbtn, mutebtn, currentTime, duration, barSize, bar, progressBar ;
// Set object references
my_track = document.getElementById('my_track');
playbtn = document.getElementById('playbtn');
mutebtn = document.getElementById('mutebtn');
currentTime = document.getElementById('currentTime');
duration = document.getElementById('fullDuration');
barSize = 300 ;
bar = document.getElementById('defaultBar')
progressBar = document.getElementById('progressBar')
//innerHTML
// Add Event Handling
playbtn.addEventListener('click',playOrPause, false) ;
mutebtn.addEventListener('click',muteOrUnmute, false) ;
bar.addEventListener("click", clickedBar,false) ;
// event handling with function
my_track.addEventListener("timeupdate", function update() {
var curmins = Math.floor(my_track.currentTime / 60);
var cursecs = Math.floor(my_track.currentTime - curmins * 60);
var durmins = Math.floor(my_track.duration / 60);
var dursecs = Math.floor(my_track.duration - durmins * 60);
if(cursecs < 10){ cursecs = "0"+cursecs; }
currentTime.innerHTML = curmins+":"+cursecs;
}, false);
my_track.addEventListener("timeupdate", function progress(){
if (!my_track.ended){
var size = parseInt(my_track.currentTime*barSize/my_track.duration);
progressBar.style.width = size + "px";
}
else{
currentTime.innerHTML = "0:00"
playbtn.style.backgroundImage = 'url("../icon/audio_play.png")';
playbtn.style.backgroundRepeat = 'no-repeat';
playbtn.style.backgroundPosition = 'center';
playbtn.style.backgroundSize = '25px 25px';
progressBar.style.width = "0px" ;
window.clearInterval(updateTime);
}
}, false);
// Functions
function playOrPause(){
if(!my_track.paused && !my_track.ended) {
my_track.pause();
playbtn.style.backgroundImage = 'url("../icon/audio_play.png")';
playbtn.style.backgroundRepeat = 'no-repeat';
playbtn.style.backgroundPosition = 'center';
playbtn.style.backgroundSize = '35px 35px';
window.clearInterval(updateTime);
}
else {
my_track.play();
playbtn.style.backgroundImage = 'url("../icon/audio_stop.png")';
playbtn.style.backgroundRepeat = 'no-repeat';
playbtn.style.backgroundPosition = 'center';
playbtn.style.backgroundSize = '35px 35px';
}
}
function muteOrUnmute(){
if (my_track.muted == true ){
my_track.muted = false ;
mutebtn.style.backgroundImage = 'url("../icon/audio_speaker.png")';
mutebtn.style.backgroundRepeat = 'no-repeat';
mutebtn.style.backgroundPosition = 'center';
mutebtn.style.backgroundSize = '25px 25px';
}
else {
my_track.muted = true ;
mutebtn.style.backgroundImage = 'url("../icon/audio_mute.png")';
mutebtn.style.backgroundRepeat = 'no-repeat';
mutebtn.style.backgroundPosition = 'center';
mutebtn.style.backgroundSize = '25px 25px';
}
}
function clickedBar(e){
if (!my_track.ended){
var mouseX = e.pageX - bar.offsetLeft ;
var newtime = mouseX*my_track.duration/barSize;
my_track.currentTime = newtime ;
progressBar.style.width = mouseX + 'px';
}
}
CSS
*{
margin: 0 ;
padding: 0 ;
}
html, body {
margin: 0 ;
padding: 0 ;
}
/*-------AUDIO STARTS HERE-----------*/
#audioplayer {
float: right ;
border: 2px solid #fff;
background-color: #515254;
width: 200px ;
-webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
margin-top: -20px ;
margin-right: 8px ;
}
#audioplayer nav {
border-radius: 4px;
}
#defaultBar {
position: absolute ;
width: 196px ;
height: 8px ;
background-color: black ;
top: 0 ;
-webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
}
#progressBar {
position: absolute ;
height: 8px ;
width: 0px ;
background-color: green ;
}
#beforebtn {
border: none ;
outline: none ;
height: 25px ;
width: 25px ;
background-image: url("../icon/before_track.png");
background-repeat: no-repeat ;
background-position: center ;
background-size: cover ;
margin-top: 6px ;
margin-left: 3px ;
float: left ;
cursor: pointer ;
}
#playbtn {
border: none ;
outline: none ;
height: 35px ;
width: 35px ;
background-image: url("../icon/audio_play.png");
background-repeat: no-repeat ;
background-position: center ;
background-size: cover ;
margin-left: 5px ;
margin-right: 5px ;
margin-top: 1px ;
float: left ;
cursor: pointer ;
}
#playtbn:target {
background-image: url("../icon/audio_stop.png");
background-repeat: no-repeat ;
background-position: center ;
background-size: cover ;
}
#nextbtn {
border: none ;
outline: none ;
height: 25px ;
width: 25px ;
background-image: url("../icon/next_track.png");
background-repeat: no-repeat ;
background-position: center ;
background-size: cover ;
float: left ;
margin-top: 6px ;
cursor: pointer ;
}
#mutebtn {
float: right ;
border: none ;
outline: none ;
height: 25px ;
width: 25px ;
background-image: url("../icon/audio_speaker.png");
background-repeat: no-repeat ;
background-position: center ;
background-size: cover ;
margin-top: 6px ;
margin-right: 3px ;
cursor: pointer ;
}
#audioplayer button {
background-color: #515254;
border-radius: 50% ;
}
#mutebtn:active, #playbtn:active , #beforebtn:active, #nextbtn:active {
position: relative ;
top: 2px ;
}
#timebox{
float: right ;
margin-top: 11px ;
margin-right: 5px ;
height: 16px ;
width: 38px ;
background-color: #515254 ;
color: #fff ;
border: 1px solid #000;
-webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
-moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
box-shadow: 1px 1px 2px rgba(0,0,0,0.4);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
#currentTime {
float: right ;
font-family: arial ;
font-size: 14px ;
}
HTML
<div ID="audioplayer">
<audio ID="my_track">
<source src="audio/take_me_baby.wav" type="audio/wav"/>
</audio>
<nav>
<div ID="defaultBar">
<div ID="progressBar"></div>
</div>
<div ID="buttons">
<button ID="beforebtn"></button>
<button ID="playbtn" class="playbtn"></button>
<button ID="nextbtn"></button>
<button ID="mutebtn"></button>
<div ID="timebox">
<span ID="currentTime">0:00</span><span ID="fullDuration"></span>
</div>
</div>
</nav>
</div>
<!-- #end audio tag -->
Hope this is clear for you guys :)
Thanks to all the help i can get!
Make sure your icons are in the right folder.
You may need to wrap your code in a window.onload:
window.onload = function() {
//... your javascript
};
http://plnkr.co/edit/kpU3oXNwhei5B6O9YKEO?p=preview
found the answer myself :)
changed my background-image from CSS to a normal tag on my html
<button ID="playbtn" onclick='this.firstChild.src="icon/audio_stop.png"'>
<img src="icon/audio_play.png"/>
</button>
and some changes on the javascript as followed:
function playOrPause(){
console.log(5);
if(!my_track.paused && !my_track.ended) {
my_track.pause();
playbtn.firstChild.src = "icon/audio_play.png";
window.clearInterval(updateTime);
}
else {
my_track.play();
playbtn.firstChild.src = "icon/audio_stop.png";
}
}
much shorter and it even works :)
btw this: "window.onload = function() { //... your javascript };"
used to help aswell :) so thanks again Clint Powell !!

Categories