change div to increase progress bar - javascript

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>

Related

How can I make a button, like a target, move in a set div when it is clicked

I am making a basic aim trainer game. I have a gameboard which is just a div with a range and a target icon which is really just a button. I want the button to move inside the range every time it is clicked.
this is my code for the gameboard and target
function targetClicked() {
score++;
document.getElementById("scoreLabel").innerHTML = score;
moveTarget();
}
function moveTarget() {
}
#gameboard {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
width: 500px;
height: 500px;
background-color: darkgray;
}
#target {
width: 75px;
height: 75px;
position: absolute;
left: 50%;
margin-right: -50%;
transform: translate(-50%, 50%);
}
<div id="gameboard">
<input hidden type="image" src="target.png" id="target" onclick="targetClicked()">
</div>
everything else such as the countdown timer and score counter work. (not shown here) I even got the gameboard and everything to dissapear when the counter reaches 0, but I don't actually know how to move the target everytime it is clicked.
Can I used something like this and inside the moveTarget function adjust the property of the buttons location?
Is there a better way to go about it or can I simply make the button move its position when its clicked?
welcome to StackOverflow.
There are a number of ways to accomplish this. You could set the style of your target element on click and use the transform property you're already using above to set the position of the target. For example:
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function targetClicked() {
const randX = getRandomInt(100);
const randY = getRandomInt(100);
document.getElementById("target").style.transform = `translate(${randX}%, ${randY}%)`;
}
If you'd like to know more you may want to look at all the different ways position can be set via CSS. Hopefully this gets you off the ground though.
Hello justinMonserrat,
I hope this will help you to solve the problem, By this you can move the image any where inside the parent element.
function randomAxis(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const img = document.getElementById("gameboard_target");
const gameboard = document.getElementById("gameboard").getBoundingClientRect();
const img_credentials = img.getBoundingClientRect();
const g_width = gameboard.width-img_credentials.width;
const g_height = gameboard.height-img_credentials.height;
img.onclick = function(){
const y_axis = randomAxis(0,g_width);
const x_axis = randomAxis(0,g_height);
this.style.cssText = `transform:translate(${x_axis}px,${y_axis}px)`
};
#gameboard{
border:2px solid;
width:300px;
height:300px;
background-color: darkgray;
}
#gameboard img{
width:30px;
height:30px;
border-radius: 50%;
transition: transform .5s cubic-bezier(.22,.61,.36,1);
cursor:pointer;
}
#gameboard img:active{
box-shadow: 0px 0px 13px 3px #ecebeb;
}
<div id="gameboard">
<img id="gameboard_target" src="https://justinmonserrat.github.io/target-practice/target.png" />
</div>
The input type was not button, it is a image. You want to move the image?

Javascript Slider with Multiple Allowed sections/timeslots

I want to implement a time-slot selector in jquery/javascript slider form.
There are a few slider libraries out there such as Ion Slider, jQRangeSlider etc. but I don't know how I would be going about this. It doesn't look like they support multiple "dead-zones".
I want the user to be able to select a timeslot (from and to) during a particular day. To select the day, I have implemented a date picker, then for the date, I retrieve the already occupied slots for instance:
07h00 - Available
07h30 - Available
08h00 - Occupied
08h30 - Occupied
09h00 - Occupied
09h30 - Available
...
18h30 - Available
19h00 - Available
So the range picker must look like this:
The user should only be able to select a time zone in the available sections (blue) and drag the start slider between the "available" section, and the end selector will move along with it. There might be multiple unavailable zones (Red).
Is this possible with the libraries already out there or is this a case of roll my own?
I have thought about using a bunch of check boxes then check all the boxes between the start and end time-slots, and disable the already occupied slots, but I think a slider like this would be much more user friendly to use, functionally and visually.
A double slider can be made with very little effort by overlaying two sliders on top of each other using CSS. You need to listen to the onchange events of these two and reset the slider to previous value or closet non dead region when set to a dead region.
var deadZones = [[2,3], [6,7]];
function showVal(input) {
deadZones.forEach(([from, to]) => {
// reset to old value if in dead zone
if(from <= input.value && input.value <= to)
input.value = input.oldValue;
});
input.oldValue = input.value;
//console.log(input.id, input.value);
displayValues();
}
function displayValues() {
var a = $('#a').val();
var b = $('#b').val();
$('#slider-values').text(`Min: ${Math.min(a,b)} Max: ${Math.max(a,b)}`);
}
displayValues();
html,body{
margin: 0; padding: 0;
}
#a, #b{
position: absolute;
top: 30px;
display: block;
z-index: 100;
}
#b {
top: 60px;
}
/* from: https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/ */
input[type=range] {
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
width: 90%; /* Specific width is required for Firefox. */
background: transparent; /* Otherwise white in Chrome */
margin-left: 5%;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
automatic */
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; /* Add cool effects to your sliders! */
position: relative;
}
input[type=range]#a::-webkit-slider-thumb {
top: 100px;
}
input[type=range]#b::-webkit-slider-thumb {
top: 70px;
}
.slider-bg {
width: 100%;
margin: 0; padding: 0;
margin-left: 2.5%;
position: relative;
z-index: 1;
top: 135px;
}
.slider-bg div {
display: inline-block;
width: 9%;
margin: 0; padding: 0;
text-align: center;
border-top: 1px solid green;
padding-top: 20px;
}
.slider-bg div.disabled {
border-top: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="a" type="range" min="1" max="10" value="1" oninput="showVal(this)" onchange="showVal(this)" />
<input id="b" type="range" min="1" max="10" value="9" oninput="showVal(this)" onchange="showVal(this)"/>
<hr />
<div class="slider-bg">
<div>1</div>
<div class="disabled">2</div>
<div class="disabled">3</div>
<div>4</div>
<div>5</div>
<div class="disabled">6</div>
<div class="disabled">7</div>
<div>8</div>
<div>9</div>
<div>10</div>
</div>
<div id="slider-values"></div>
I have decided to implement an ionRangeSlider with custom slots from 05h30 to 19h30. A separate array of used time-slots to which I compare in the onChange event.
var slider = $("#timeslotSlider").ionRangeSlider({
type: "double",
grid: true,
from: 1,
from_value: "06h00",
to: 2,
to_value: "06h30",
values: timeslotvalues,
onChange: function (data) {
timeslotSetSelectedText(data);
}
});
var sliderdata = slider.data("ionRangeSlider");
var dt = sliderdata.result.from_value != null ? sliderdata.result : sliderdata.options;
timeslotSetSelectedText(dt);
The timeslotSetSelectedText function compares the selected range to the used slots then display a message "Available" or "Overlaps Existing time-slot"
The same function is used to Validate the selected slot before sending it to the server.

My div won't change width with my javascript function

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>

How to build inline rating using JavaScript or jQuery?

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>

Progress bar with slide ability

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/

Categories

Resources