I have made a makeshift progress bar with two divs, styled with css to fit one in another to make the progress bar. I have a button that changes the width of the inside div to go up when I click the button, but the button click does not change the width of the div. I made sure I made no errors, the javascript console in my chrome browser gives no errors when I click the button. Anyways, here is my code:
function clickMe() {
var newExp = parseInt(document.getElementById("expHold").innerHTML);
document.getElementById("bar2").style.width = newExp + 'px';
document.getElementById("expHold").innerHTML += '+1';
document.getElementById("expHold").innerHTML = eval(document.getElementById("expHold").innerHTML);
}
#bar1 {
border: 2px solid gold;
height: 15px;
width: 100px;
background-color: blue;
border-radius: 8px;
}
#bar2 {
height: 15px;
width: 1px;
background-color: skyblue;
border-radius: 8px;
}
<div id="bar1">
<div id="bar2">
</div>
</div>
<p>
<input type="button" value="Click me" onClick="clickMe()" />
<span id="expHold" style="color:black;">1</span>
I would appreciate any help telling me what I am doing wrong, thanks!
Please do not use inline JavaScript. It reduces readability and maintainability.
You should use a JavaScript variable to store the exp, this way you don't have to repeatedly query the DOM, which is process intensive.
You should cache the DOM objects instead of creating new ones on each iteration.
You can increment the previously created exp variable by using the prefix increment modifier
The prefix increment modifier will return the incremented value.
The postfix increment modifier will return the value before incrementing.
var exp = 0, current;
var bar1 = document.getElementById("bar1");
var bar2 = document.getElementById("bar2");
var hold = document.getElementById("expHold");
var max = bar1.clientWidth;
document.getElementById('my-button').onclick = function() {
// Don't go past the end.
if(bar2.clientWidth < max) {
current = ++exp;
hold.textContent = current;
bar2.style.width = current + 'px';
}
}
#bar1 {
border: 2px solid gold;
height: 15px;
width: 100px;
background-color: blue;
border-radius: 8px;
}
#bar2 {
height: 15px;
width: 0px;
background-color: skyblue;
border-radius: 8px;
}
<div id="bar1">
<div id="bar2">
</div>
</div>
<p>
<input type="button" value="Click me" id="my-button" />
<span id="expHold" style="color:black;">0</span>
Related
I'm working to have my progress bar increase when a specific word is said (Bingo)
This is a conversation between a user and a chatbot, where the user is trying to guess a secret that the chatbot olds. Every time the user gets it right, the chatbot replies with "Bingo! " I was hoping to increase the progress bar every time the chatbot replies with "Bingo! " and when the progress bare hits 100% it should restart back to 0%. I get the progress bar shows, but it does not increase. I was thinking of having to loop through the div to look for "Bingo" and change the div in the progress bar. Or simply have a "Bingo" as a variable and match it to the div="bingo1" and then increase the progress bar. What would be the most efficient way?
I'm using chatterbot which contains the conversation between the user and chatbot in a .yml file, so it is possible to do something there
function myBingo(){
if (document.getElementById('bingo1').innerHTML.indexOf("Bingo")){
// change progress bar to 10%
}
}
#progress {
width: 500px;
border: 1px solid black;
position: relative;
padding: 3px;
}
#percent {
position: absolute;
left: 50%;
}
#bar {
height: 20px;
background-color: green;
width: 0%;
}
<!-- I added an id here -->
<div class="msg-text" id="bingo1">Bingo! The secret is Garfield</div>
<div id="progress">
<span id="percent">0%</span>
<div id="bar"></div>
</div>
He might have given a different answer as he didn't quite understand what he wanted. In the solution below, the progress bar will be increased by the number of Bingo expressions entered into the item whose id value is bingo1.
If you're asking something different, please edit the question or comment below this answer.
let percent = document.getElementById('percent');
let bar = document.getElementById('bar');
let input = document.getElementById('bingo1');
let counter = 0;
function update() {
if (input.value.indexOf("Bingo") != -1)
{
var count = (input.value.match(/Bingo/g) || []).length;
counter = count * 10;
if(counter >= 100)
counter = 100;
percent.innerHTML = `${counter}%`;
bar.style.width = `${counter}%`;
}
}
input.addEventListener('input', update);
#progress {
width: 500px;
border: 1px solid black;
position: relative;
padding: 3px;
}
#percent {
position: absolute;
left: 50%;
}
#bar {
height: 20px;
background-color: green;
width: 0%;
}
<label>Input: </label>
<input class="msg-text" id="bingo1"><br><br>
<div id="progress">
<span id="percent">0%</span>
<div id="bar"></div>
</div><br><br>
I have reviewed tonnes of articles and all solutions only update the visually displayed value as opposed to the actual value within the input tag itself.
When I click on a button a modal appears with a text input to enter a code. We will call it input1
Upon entering the code and exiting the modal the button updates to the code entered and a hidden input value gets updated as well. However the actual tags value="" remains the same.
I have tried numerous ways but all seem to only update the visual and not the true value.
Here is what I have so far but it only updates the value you see in the browser not within the tag itself.
let promoModal = document.getElementById("promoModal");
let promoBtn = document.getElementById("promo");
let promoSpan = document.getElementsByClassName("promoClose")[0];
promoBtn.onclick = function() {
promoModal.style.display = "block";
}
promoSpan.onclick = function() {
promoModal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == promoModal) {
promoModal.style.display = "none";
}
}
function updatePromo() {
let promoValue = document.getElementById("promo-value");
let producePromo = document.getElementById("promo");
let copyPromo = document.getElementById("promo-value-copy");
producePromo.innerHTML = promoValue.value;
copyPromo.innerHTML = promoValue.value;
}
/* THE MODAL */
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 5px 20px;
border: 1px solid #888;
width: 280px;
position: relative;
}
}
/* The Close Button */
.adultClose,
.promoClose {
color: #aaaaaa;
position: absolute;
right: 5px;
top: 0px;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
<button id="promo" type="button" class="promo">
<span class="promoCode">Promo Code +</span>
</button>
<input type="hidden" id="promo-value-copy" value="test">
<!-- Promo Modal -->
<div id="promoModal" class="modal">
<div class="modal-content">
<span class="promoClose">×</span>
<input type="text" class="promo-value" id="promo-value" value="" placeholder="Promotional code" onchange="updatePromo()">
</div>
</div>
I stripped the styling to get to the meat and potatoes.
How can I update the actual value="test" to the new value using javascript?
The innerHTML is used for changing HTML content, so for instance you can use it for changing the content of a paragraph <p id="text-to-change"></p>.
To change the input value you can use the .value property of the object.
Try to change the following line copyPromo.innerHTML = promoValue.value; with copyPromo.value = promoValue.value;
You need to change the value like this:
document.getElementById("promo-value-copy").value = promoValue.value;
so going with Barmar's suggestion I was able to update my updatePromo function to both produce the value as well as update the DOM value.
Here is the updated function. I hope it helps the community.
function updatePromo() {
let promoValue = document.getElementById("promo-value");
let producePromo = document.getElementById("promo");
let copyPromo = document.getElementById("promo-value-copy");
producePromo.innerHTML = promoValue.value;
copyPromo.innerHTML = promoValue.value;
copyPromo.setAttribute("value", promoValue.value); // suggestion given by Barmar
}
I had to leave the other element as it adds the text after the form field which is actually needed for this project however typically would not be needed.
I need to build inline rating for tv shows for example. Max rating I put in jQuery code, current rating in html document. This is how I found the way to do this.
$(document).ready(function() {
var maxRating = $('.rate-line').width();
var maxRating = 6; //max-rating
var currentRatingFirst = $('.first-rd').text();
var calc = (currentRatingFirst / maxRating) * 100 + "%";
$('.first-rl span.fill').width(calc);
});
.rate-line {
border: 1px solid #bababa;
background: #fff;
position: relative;
vertical-align: middle;
margin-right: 1.25em;
overflow: hidden;
width: 50%;
height: 20px;
}
.rate-line, .rate-data, .fill {
display:inline-block;
}
.fill {
background: #ff6292;
height: 22px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">4.56</span>
</div>
But, I need to create 6 rating lines for this month, then 6 for next and so on. And every time I must give new unique classes to make it work. And code becomes huge. And one more, all this rating nested to bootstrap carousel items and when I duplicate it nothing works .I'm not good in JavaScript at all and I'm asking your help. Would you please tell me how to make it work correctly and make it easier?
In this case it makes sense to create basin custom plugin, so you can easily reuse it without duplicating code.
Here is a very basic example of how you can extend jQuery prototype with a new method:
$.fn.rating = function(options) {
return this.each(function() {
var maxRating = $(this).find('.rate-line').width();
var maxRating = 6;
var currentRatingFirst = $(this).find('.first-rd').text();
var calc = (currentRatingFirst / maxRating) * 100 + "%";
$(this).find('.first-rl span.fill').width(calc);
});
};
$(document).ready(function () {
$('.rating').rating();
});
.rate-line {
border: 1px solid #bababa;
background: #fff;
position: relative;
vertical-align: middle;
margin-right: 1.25em;
overflow: hidden;
width: 50%;
height: 20px;
}
.rate-line, .rate-data, .fill {
display:inline-block;
}
.fill {
background: #ff6292;
height: 22px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rating">
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">4.56</span>
</div>
<div class="rating">
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">3.21</span>
</div>
I made a slider using html and CSS which displays its value on change. I styled it using CSS using the <style> tag. I then went on to making the value display text. I want to display "Starter" when the slider hits 20.
I don't know what I am doing wrong and why this isn't working for me. I would like to use the most user-friendly version of this. If possible, please explain what I did wrong.
<html>
<style>
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 25px;
border: 1px solid;
background-color: #0066FF;
}
input[type="range"]::-webkit-slider-thumb{
-webkit-appearance: none;
width: 25px;
height: 25px;
border: 1px solid;
background-color: #FFF;
}
</style>
</html>
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" step="20" value="0">
<div align="center" style="font-size:25px;"><output name="amount" for="rangeInput">0</output></div>
</form>
<script type="text/javascript">
var rangeInput = document.getElementById("rangeInput").value
if(rangeInput = 20){
text = "starter"
}
How can i get my slider to RESET on value 0?
at the moment, if i go from 20 to 0, it stays displaying Starter , i would like it to remove that. Is this possible?
you need '==' instead of '=' with your if statement
var rangeInput = document.getElementById("rangeInput").value
if(rangeInput == 20){
text = "starter"
}
See this question, as well: Range Slider Event Handler Javascript
You're going to want to look into event listeners-- you want to have a listener bound to the slider so that when the user changes the value, your code can respond accordingly.
You need to listen for onchange event. Also, you need to use == instead of = to compare values. The following code should work -
function updateValue() {
var rangeInput = document.getElementById("rangeInput").value
if (rangeInput == 20) {
document.getElementById("text").innerHTML = 'starter'
} else {
document.getElementById("text").innerHTML = ''
}
}
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 25px;
border: 1px solid;
background-color: #0066FF;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 25px;
height: 25px;
border: 1px solid;
background-color: #FFF;
}
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" step="20" value="0" onchange="updateValue()">
<div align="center" style="font-size:25px;">
<output name="amount" for="rangeInput">0</output>
</div>
</form>
<div id="text"></div>
I am new to JavaScript/CSS (basically the whole world of web dev) and I am really struggling to create the following widget. I created a picture of what I want to make to make it more clear.
The Play/Pause and Stop button are ready. Loop checkbox is no problem. But the progress bar is painful. The two markers are supposed to mark the point from where the file would start playing and where it would stop. The progress bar is also supposed to be click-able, so if I want to access a certain point in time, then its possible.
What I tried so far
jQuery UI slider: For a sliding progress bar and use that draggable slider to access a certain point in audio file. Works fine. But no markers and looks really ugly. Don't how to change it.
<progress> tag: not very flexible. Marker? Clicking?
<div> tag: there seems to be no way to get the point where I clicked.
So, what do you guys recommend? How should I proceed?
Canvas Alternative
You might want to use a canvas and draw your own progress bar element within it.
Here are some canvas progress bar tutorials:
How to create a progress bar with HTML5
A progress bar using HTML5 canvas
Doing it with <progress>
To access the clicked position within a DOMElement, you can proceed with the click event's properties: clientX and clientY (MDN Source), like so:
HTML
<div class="marker" id="StartMarker">^</div>
<div class="marker" id="StopMarker">^</div>
<progress id="progress" value="0" min="0" max="100">0%</progress>
<form id="choice">
<button id="marker1">Beginning marker</button>
<button id="marker2">Ending marker</button>
<input type="hidden" id="markerValue" value="0" />
</form>
JavaScript (not optimized)
document.getElementById('progress').onclick = function (event, element) {
/* Math.floor((event.offsetX / this.offsetWidth) * 100) */
var newProgress = event.offsetX;
document.getElementById('choice').style.display = "block";
document.getElementById('markerValue').setAttribute('value', newProgress);
document.getElementById('marker1').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
var marker = startMarker;
marker.style.display = "block";
startMarker.style.display = "block";
startMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
startMarker.style.left = newProgress + "px";
};
document.getElementById('marker2').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
stopMarker.style.display = "block";
stopMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
stopMarker.style.left = newProgress + "px";
};
};
CSS
.marker {
position:absolute;
top:24px;
left:9px;
display:none;
z-index:8;
font-weight:bold;
text-align:center;
}
#StartMarker {
color: #CF0;
}
#StopMarker {
color:#F00;
}
#choice {
display:none;
}
progress {
display: inline-block;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 300px;
height: 20px;
padding: 3px 3px 2px 3px;
background: #333;
background: -webkit-linear-gradient(#2d2d2d, #444);
background: -moz-linear-gradient(#2d2d2d, #444);
background: -o-linear-gradient(#2d2d2d, #444);
background: linear-gradient(#2d2d2d, #444);
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 15px;
box-shadow: 0 1px 0 rgba(255, 255, 255, .2);
}
Live Demo
Using simple blocks for that is possible. Your layout would look like this (simplified):
HTML
<div class="progressbar">
<div class="bar">
<div class="progress" style="width: 30%;">
</div>
</div>
<div class="markers">
<div class="right" style="width: 70%;">
<div class="marker">
</div>
<div class="left" style="width: 20%;">
<div class="marker">
</div>
</div>
</div>
</div>
</div>
SCSS
.progressbar {
width: 20em;
background: grey;
.bar {
height: 2em;
.progress {
background: blue;
height: 100%;
}
}
.markers {
height: 1em;
background: white;
.right {
height: 100%;
background: red;
.marker {
width: 1em;
height: 100%;
background: green;
position: relative;
float: right;
}
.left {
background: white;
height: 100%;
}
}
}
}
The operations can be quite difficult
jQuery
$('.bar').click(function(e){
$(this).find('.progress').css('width', (e.offsetX / this.offsetWidth)*100+'%');
});
will set the Progressbar properly on clicks.
For the markers though you will need mousedown, mousemove, mouseleave events, since you got 2 of them.
Example
http://jsfiddle.net/JXauW/