Why is my drawing canvas offset within the page? - javascript

It's very hard to explain. But I'll try, the whole canvas is offset. I'm not sure how this even happened or how to fix it. It's like when your mouse is in the top left corner of the page, and you started in the center, it matches up with the top left corner of the canvas element itself. Use the code snippets to see what I'm talking about.
let currentColor = null;
let inputs = document.getElementsByClassName("style2");
for (const input of inputs) {
input.addEventListener("click", (e) => {
if (e.detail !== 2) e.preventDefault();
});
}
let arr = [];
for (let i = 0; i < inputs.length + 1; i++) {
arr.push(i.toString());
}
arr.shift();
for (const input of inputs) {
input.addEventListener("input", (e) => {
const { value } = document.getElementById(e.target.id);
currentColor = value;
$("#selectedColor").css("background-color", value);
})
input.addEventListener("click", (e) => {
const { value } = document.getElementById(e.target.id);
currentColor = value;
$("#selectedColor").css("background-color", value);
})
}
var rangeslider = document.getElementById("sliderRange");
const setSize = document.getElementById("setSize")
const submit = document.getElementById("submit")
submit.addEventListener("click", (e) => {
rangeslider.value = setSize.value
})
const button = document.getElementById("clear")
// create canvas element and append it to document body
var canvas = document.getElementById('canvas');
// some hotfixes... ( ≖_≖)
// get canvas 2D context and set him correct size
var ctx = canvas.getContext('2d');
resize();
// last known position
var pos = { x: 0, y: 0 };
window.addEventListener('resize', resize);
button.addEventListener('click', clear)
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mousemove', setPosition);
// new position from mouse event
function setPosition(e) {
let canvas = document.getElementById("canvas")
pos.x = e.clientX
pos.y = e.clientY
}
// resize canvas
function resize() {
ctx.canvas.width = 650;
ctx.canvas.height = 375;
}
function draw(e) {
// mouse left button must be pressed
if (e.buttons !== 1) return;
let canvas = document.getElementById('canvas');
console.log(pos)
ctx.beginPath(); // begin
ctx.lineWidth = rangeslider.value;
ctx.lineCap = 'round';
ctx.strokeStyle = currentColor;
ctx.moveTo(pos.x, pos.y); // from
setPosition(e);
ctx.lineTo(pos.x, pos.y); // to
ctx.stroke(); // draw it!
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
html, body {
height: 100%;
width: 100%;
font-family: sans-serif;
background-color: #B3B7B5;
/* overflow: hidden; */
}
.style2 {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: transparent;
width: 35px;
height: 35px;
border: none;
cursor: pointer;
}
.style2::-webkit-color-swatch {
border-radius: 50%;
border: 3px solid #000000;
}
.style2::-moz-color-swatch {
border-radius: 50%;
border: 3px solid #000000;
}
.box {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 5px;
max-width: 320px;
margin: 0 auto;
padding: 7.5px 10px;
}
.box1 {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 5px;
max-width: 9999px;
margin: 0 auto;
padding: 10px 10px;
}
.box5 {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 5px;
max-width: 650px;
margin: 0 auto;
padding: 10px 10px;
}
.box2 {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 5px;
max-width: 9999px;
margin: 0 auto;
padding: 10px 10px;
}
#selectedColor {
width: 100px;
height: 30px;
border: 3px solid black;
border-radius: 5px;
background-color: black;
}
.canvas {
height: 350px;
width: 650px;
border: 3px solid black;
border-radius: 5px;
background-color: white;
cursor: crosshair;
position: relative;
/* left: 50%; */
}
#clear {
width: 50px;
height: 35px;
font-size: 15px;
border-radius: 5px;
}
#submit {
width: 59px;
height: 23px;
margin: auto;
left: 35%;
border-radius: 5px;
position: relative;
}
.rangeslider {
width: 50%;
}
.myslider {
-webkit-appearance: none;
background: #FCF3CF ;
width: 50%;
height: 20px;
opacity: 2;
}
.myslider::-webkit-slider-thumb {
-webkit-appearance: none;
cursor: pointer;
background: #34495E ;
width: 5%;
height: 20px;
}
.myslider:hover {
opacity: 1;
}
.rangeslider {
left: 38%;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>replit</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box5">
<canvas class="canvas" id="canvas"></canvas>
</div>
<div class="box1">
<button id="clear">Clear</button><br>
</div>
<div class="box1">
<div class="rangeslider">
<input type="range" min="1" max="100" value="5" class="myslider" id="sliderRange">
</div>
</div>
<div class=box1>
<div>
<input id="setSize" type="text" placeholder="Set Brush Size... (Max 100)">
<br>
<button type="submit" id="submit" for="setSize">Submit</button>
</div>
</div>
<div class="box">
<div class="container">
<input type="color" value="#000000" class="style2" id="1" />
</div>
<div class="container">
<input type="color" value="#ffffff" class="style2" id="2" />
</div>
<div class="container">
<input type="color" value="#ffffff" class="style2" id="3" />
</div>
<div class="container">
<input type="color" value="#ffffff" class="style2" id="4" />
</div>
<div class="container">
<input type="color" value="#ffffff" class="style2" id="5" />
</div>
</div>
<div class="box">
<label for="selectedColor">Current Color:</label>
<div id="selectedColor"></div>
</div>
<script src="script.js"></script>
</body>
</html>
I know this code is kind of weird but please bare with me.

This is actually a simple one to solve. You merely forgot to offset the clientX and clientY. You see, those coordinates are in window space therefore (0,0) will be the top left of your window. If your canvas is also in the top left then everything will seem all fine but in your case the canvas is center so the coordinates won't align. This can be fixed by subtracting the coordinates by the screen position of the canvas.
Here's an example:
function setPosition(e) {
let canvas = document.getElementById("canvas")
let bounds = canvas.getBoundingClientRect()
pos.x = e.clientX - bounds.x
pos.y = e.clientY - bounds.y
}
You can read more about getBoundingClientRect over at https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

The way of calculating the position of the mouse is not appropriate, it is necessary to take into account the deviation of the canvas compared to the viewport. You can't do it using getBoundingClientRect() :
function setPosition(e) {
const canvas = document.getElementById("canvas");
const bounds = canvas.getBoundingClientRect();
pos.x = e.clientX - bounds.left;
pos.y = e.clientY - bounds.top;
}
But you also have to fix the .canvas css class by removing width and height or by setting the same height than in the resize function.
https://codepen.io/Joulss/pen/BaPYgpZ?editors=1111

Related

Unwanted blinking effect on button

I want to show a clickable button over the mouse cursor, whenever the user hover's over an image.
Code I am using: codepen
const box = document.getElementById("box");
function movebox(e) {
box.style.left = event.clientX - 20 + 'px';
box.style.top = event.clientY - 20 + 'px';
box.style.display = 'block';
}
function removebox() {
box.style.display = 'none';
}
function click() {
console.log("clicked")
}
#maindiv {
border: 1px solid blue;
padding: 1px;
display: flex;
justify-content: center;
text-align: center;
align-items: center;
min-height: 100vh;
}
#maindiv img {
max-width: 400px;
max-height: 400px;
object-fit: scale-down;
border: 1px solid red;
}
#box {
position: absolute;
z-index: 100;
display: none;
}
<!-- bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script><div id="maindiv">
<img src="https://images.unsplash.com/photo-1563884993747-a52423c68196?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" onmousemove="movebox(event)" onmouseout="removebox()" />
<button id="box" class="btn btn-primary" onclick="click()">click</button>
</div>
Problems:
Getting unwanted blinking effect on button.
I have tried using the pointer-events: none property on button, but it also disables the onclick events.
Your function can not be named "click" because when you call it you are calling the built in click method.
Updated your code to rely on CSS to show and hide the element. Added hove to the img and the button.
Fixed a bug where you did not account for scroll position.
const box = document.getElementById("box");
function movebox(e) {
box.style.left = window.scrollX + event.clientX - 20 + 'px';
box.style.top = window.scrollY + event.clientY - 20 + 'px';
}
function clickMe() {
console.log("clicked")
}
#maindiv {
border: 1px solid blue;
padding: 1px;
display: flex;
justify-content: center;
text-align: center;
align-items: center;
min-height: 100vh;
}
#maindiv img {
max-width: 400px;
max-height: 400px;
object-fit: scale-down;
border: 1px solid red;
}
#box {
position: absolute;
z-index: 100;
display: none;
transition: all .25s;
}
#maindiv img:hover + #box,
#box:hover
{
display: block;
}
<!-- bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script><div id="maindiv">
<img src="https://images.unsplash.com/photo-1563884993747-a52423c68196?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" onmousemove="movebox(event)" />
<button id="box" class="btn btn-primary" onclick="clickMe()">click</button>
</div>

How can I make a different text based on the user's choices?

I'm making a Tic Tac Toe game where the user can choose if they play X or O. How do I change the onclick function to display X if they chose X, or O if they chose O?
My code right now doesn't work since it only displays X even if I selected O from the two buttons.
Note: The other boxes don't have a function yet. To see the problem I'm talking about, click the first box on the upper left.
#import url('https://fonts.googleapis.com/css2?family=Koulen&family=VT323&display=swap');
#import url('https://fonts.googleapis.com/css2?family=Lobster&family=Signika+Negative:wght#400;500;600&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
text-align: center;
background-color: #1C2C54;
color: #D175B7;
font-family: 'Signika Negative', sans-serif;
}
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 20px;
margin: auto;
position: absolute;
top: 50%;
bottom: 50%;
left: 50%;
right: 50%;
}
h1 {
font-family: 'VT323', monospace;
font-size: 3rem;
}
.text-container {
display: flex;
flex-direction: column;
width: 300px;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto;
background-color: #4BC3B5;
padding: 20px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 30px;
font-size: 30px;
text-align: center;
cursor: pointer;
}
.button-container {
display: flex;
flex-direction: row;
gap: 10px;
}
button {
padding: 3px 20px;
background-color: #4BC3B5;
color: white;
border: 3px solid #34a396;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #2c8d82;
border: 3px solid #124640;
}
button:focus {
background-color: #2c8d82;
border: 3px solid #124640;
}
.score-container {
display: flex;
flex-direction: column;
gap: 10px;
width: 300px;
justify-content: center;
color: white;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic Tac Toe</title>
</head>
<body>
<main>
<div class="text-container">
<h1>Tic Tac Toe</h1>
</div>
<div class="grid-container">
<div class="grid-item" id="grid1" onclick="clickBox1()"></div>
<div class="grid-item" id="grid2" onclick="clickBox2()" ></div>
<div class="grid-item" id="grid3" onclick="clickBox3()"></div>
<div class="grid-item" id="grid4" onclick="clickBox4()"></div>
<div class="grid-item" id="grid5" onclick="clickBox5()"></div>
<div class="grid-item" id="grid6" onclick="clickBox6()"></div>
<div class="grid-item" id="grid7" onclick="clickBox7()"></div>
<div class="grid-item" id="grid8" onclick="clickBox8()"></div>
<div class="grid-item" id="grid9" onclick="clickBox9()"></div>
</div>
<div class="button-container">
<button id="x-el" onclick="selectX()">X</button>
<button id="o-el" onclick="selectO()">O</button>
</div>
<div class="score-container">
<p id="playerscore">Player Score:</p>
<p id="compscore">Computer Score:</p>
</div>
</main>
<script>
// Grab the elements
let xBtn = document.getElementById('x-el')
let oBtn = document.getElementById('o-el')
let playerScoreDisplay = document.getElementById('playerscore')
let compScoreDisplay = document.getElementById('compscore')
let x = 'X'
let o = 'O'
// Grabbing individual boxes
let box1 = document.getElementById('grid1');
let box2 = document.getElementById('grid2');
let box3 = document.getElementById('grid3');
let box4 = document.getElementById('grid4');
let box5 = document.getElementById('grid5');
let box6 = document.getElementById('grid6');
let box7 = document.getElementById('grid7');
let box8 = document.getElementById('grid8');
let box9 = document.getElementById('grid9');
/*
let boxes = document.querySelectorAll("div.grid-item")
*/
// Selecting x or o
function selectX() {
alert('You selected X!');
}
function selectO() {
alert('You selected O!');
}
// Function for each box
function clickBox1() {
if (selectX) {
box1.innerHTML = x;
} else if (selectO) {
box1.innerHTML = o;
}
}
</script>
</body>
</html>
You would probably want to create a variable to save the user's choice and set it depending on whether or not they clicked on "x-el" or "o-el" like so below.
Also, loop through the boxes instead of creating a function for every single box.
// user's choice
let myChoice
// Selecting x or o
function selectX() {
alert('You selected X!');
myChoice='X'
}
function selectO() {
alert('You selected O!');
myChoice='O'
}
// Function for each box
function clickBox1() {
if (myChoice==='X') {
box1.innerHTML = x;
} else if (myChoice==='O') {
box1.innerHTML = o;
}
}

functions deleting the paint canvas

I would really appreciate If someone could figure out what is wrong with my functions. I'm working on this simple paint program and I have Undo and Clear buttons. Undo is supposed to clear the last drawn line (the function deletes the last element of the array since the array consist of all the drawn lines on the canvas) and Clear just takes the canvas back to It's formal state (makes the board completely white). But every time I put any of those functions in the code my canvas just deletes Itself and I can't seem to figure out what's wrong. The function names are clear_canvas and undo_last. Any tips or solutions on how to fix or make another working example?
<head>
<img src="logo.png" style="width:50%; margin-right: auto; margin-left: 400px; ">
</head>
<style>
body, a, a:hover { cursor:url('https://66.media.tumblr.com/7659e714cab33f9d59124f924405e793/tumblr_inline_p7g82dZq1h1r466gz_75sq.png'), auto
}
body {
transform-style: preserve-3d;
background-image: url('img_girl.jpg');
background-repeat: no-repeat;
background-attachment: fixed;
}
canvas {
cursor: pointer;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 200px;
padding: 5px;
}
.tools .color-field {
height: 40px;
width: 40px;
cursor: pointer;
display: inline-block;
box-sizing: border-box;
border-radius: 50%;
border: 2px solid white;
align-self: center;
margin: 5px 5px ;
}
.color-field {
display: block;
margin-left: auto;
margin-right: auto;
}
.tools {
display: flex;
justify-content: center;
flex-direction: row;
margin-top: 110px;
}
.tools .button{
align-self: center;
width: 100px;
height: 40px;
border: 2px solid white;
cursor: pointer;
color: white;
background: #DB7093;
font-weight: bold;
margin: 0 10px;
display: block;
}
.button {
display: block;
margin-left: auto;
margin-right: auto;
}
.color-picker {
align-self: center;
margin: 0 15px;
background-color: pink;
}
.pen-range {
align-self: center;
margin: o 15px;
background-color: #DB7093;
}
.container {
width: 600px;
display: block;
margin-left: auto;
margin-right: auto;
position: absolute;
z-index:-1;
margin-left: 425px;
}
#gif {
background-image: url("gif.gif");
position: fixed;
width: 100%;
transform: translateZ(-1px);
top: 0;
left: 0;
}
</style>
<body style="background-image: url('https://images8.alphacoders.com/105/1055726.png');">
<div id="gif"> <img src="gif.gif"> </div>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> cute drawing program </title>
<div class="container">
<div id="status" style="color: white;"></div>
<img src="container.png" style="width:120%;">
</div>
<div class="field">
<canvas id="canvas"> </canvas>
<div class="tools">
<button onClick="undo_last()" type="button" class="button"> Undo </button>
<button onClick="clear_canvas()" type="button" class="button"> Clear </button>
<div onClick="change_color(this)" class="color-field" style="background: red;"></div>
<div onClick="change_color(this)" class="color-field" style="background: blue;"></div>
<div onClick="change_color(this)" class="color-field" style="background: yellow;"></div>
<div onClick="change_color(this)" class="color-field" style="background: green;"></div>
<div onClick="change_color(this)" class="color-field" style="background: orange;"></div>
<div onClick="change_color(this)" class="color-field" style="background: pink;"></div>
<div onClick="change_color(this)" class="color-field" style="background: brown;"></div>
<div onClick="change_color(this)" class="color-field" style="background: gray;"></div>
<div onClick="change_color(this)" class="color-field" style="background: black;"></div>
<div onClick="change_color(this)" class="color-field" style="background: white;"></div>
<input onInput="draw_color = this.value" type="color" class="color-picker">
<input type="range" min="1" max="100" class="pen-range" onInput="draw_width = this.value">
</div>
</div>
<script>
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth = 650;
canvas.height = 350;
let context = canvas.getContext("2d");
let start_background_color ="white";
context.fillStyle = start_background_color;
context.fillRect(0, 0, canvas.width, canvas.height);
let draw_color = "black";
let draw_width = "2";
let is_drawing = false;
let restore_array =[];
let index = -1;
function change_color(element) {
draw_color = element.style.background;
}
canvas.addEventListener("touchstart", start, false);
canvas.addEventListener("touchmove", draw, false);
canvas.addEventListener("mousedown", start, false);
canvas.addEventListener("mousemove", draw, false);
canvas.addEventListener("mtouchstart", stop, false);
canvas.addEventListener("mouseup", stop, false);
canvas.addEventListener("mouseout", stop, false);
function start(event) {
is_drawing = true;
context.beginPath();
context.moveTo(event.clientX - canvas.offsetLeft,
event.clientY - canvas.offsetTop);
event.preventDefault();
}
function draw(event) {
if ( is_drawing ) {
context.lineTo(event.clientX - canvas.offsetLeft,
event.clientY - canvas.offsetTop);
context.strokeStyle = draw_color;
context.lineWidth = draw_width;
context.lineCap = "round";
context.lineJoin = "round";
context.stroke();
}
event.preventDefault();
}
function stop(event) {
if (is_drawing) {
context.stroke();
context.closePath();
is_drawing = false;
}
event.preventDefault();
if (event.type != 'mouseout'){
restore_array.push(context.getImageData(0, 0, canvas.width, canvas.height));
index += 1;
}
}
function undo_last(){
if (index <= 0) {
clear_canvas();
}
else {
index -=1;
restore _array.pop();
context.putImageData(restore_array[index], 0, 0);
}
}
function clear_canvas() {
context.fillStyle = start_background_color;
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillRect(0, 0, canvas.width, canvas.height);
restore_array = [];
index = -1;
}
</script>
</body>
</html>
You should use console.log. You should also be getting an error that helps identify your issue when you run the script.
Check this line in undo_last
restore _array.pop();
It should be
restore_array.pop();

Progressbar with vertical line

I am implementing a simulation of a Dutch- and an English-auction in otree.
For the interface, I am using a progress bar for the price that the supplier gets.
In the English-auction the price increases every half second and in the Dutch-auction the price decreases every half second.
Now I want to add a vertical line for the costs of the supplier, which changes every round.
How can i add a vertical line to the progress bar?
<style>
#myProgress {
width: 100%;
background-color: #ddd;
}
#myCosts {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 100%;
height: 30px;
background-color: #40bf80;
text-align: center;
line-height: 30px;
color: white;
}
#costLine{
width: 0%;
height: 30px;
background-color: #FF0000;
text-align: center;
line-height: 30px;
color: white;
}
.bg-info{
background-color: #ddd;
}
</style>
Your costs for this round are:
<div id="myCosts">
<div id="costLine">{{player.cost}}</div>
</div>
Current price is:
<div id="myProgress">
<div id="myBar">$200</div>
</div>
<p></p>
<p id="Message"></p>
<script>
var left_line = ({{player.cost|json}}-101);
var right_line = (200-{{player.cost|json}});
let cost = {{player.cost|json}}
let bot_stop = {{player.bot_stop|json}};
let price = {{Constants.start_value|json}};
var Auction;
var Auction2;
document.getElementById("costLine").innerHTML = "$"+cost;
document.getElementById("costLine").style.width = cost-100+'%';
function startAuction(){
document.getElementById("stop_button").disabled = false;
document.getElementById("start_button").disabled = true;
Auction = setInterval(function(){
if(price == bot_stop){
document.getElementById("Message").innerHTML = 'The other supplier has dropped out. You win with a price of ' + bot_stop;
document.getElementById("stop_button").innerHTML = 'Next Page'
stopAuction();
}
if(price != bot_stop){
price = price -1;
document.getElementById("myBar").innerHTML='$'+price;
document.getElementById("myBar").style.width = (price-100) +'%';
}
},500)
}
function stopAuction() {
document.querySelector("[name=winning_price]").value = price;
document.getElementById("stop_button").innerHTML = 'Next Page'
clearInterval(Auction);
}
</script>
<button type="button" class="otree-btn-next btn btn-primary" id="start_button" onclick="startAuction()">Start Auction</button>
<button class="otree-btn-next btn btn-primary" disabled id="stop_button" onclick="stopAuction()">Drop Out</button>
<p></p>
<p></p>
<input type="hidden" name="winning_price" />
Add a child element <div id=myBarPrice></div> to <div id="myProgress">.
Add position: relative; attribute to the #myProgress selector.
Add new style block for a new element:
#myBarPrice {
background-color: #FF0000;
width: 2px;
height: 100%;
position: absolute;
right: 100%;
top: 0;
}
Set #myBarPrice position with js:
...
document.getElementById("costLine").innerHTML = "$"+cost;
document.getElementById("costLine").style.width = cost-100+'%';
document.getElementById("myBarPrice").style.right = cost+'%'; // <=====
function startAuction(){
document.getElementById("stop_button").disabled = false;
document.getElementById("start_button").disabled = true;
...
Here is a mockup in codepen.io
CSS code:
#myProgress {
width: 100%;
background-color: #ddd;
position: relative;
}
#myCosts {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 80%;
height: 30px;
background-color: #40bf80;
text-align: center;
line-height: 30px;
color: white;
}
#myBarPrice {
background-color: #FF0000;
width: 2px;
height: 100%;
position: absolute;
right: 40%;
top: 0;
}
#costLine{
width: 60%;
height: 30px;
background-color: #FF0000;
text-align: center;
line-height: 30px;
color: white;
}
.bg-info{
background-color: #ddd;
}
HTML code:
Your costs for this round are:
<div id="myCosts">
<div id="costLine">{{player.cost}}</div>
</div>
Current price is:
<div id="myProgress">
<div id="myBar">$200</div>
<div id=myBarPrice></div>
</div>

Grow and shrink the input

I am looking for a way to control the size of my input element in the way similar to divs.
.main {
width: 100%;
display: flex;
}
.line {
min-width: 2rem;
display: flex;
}
.input {
flex: 1 1 auto;
min-width: 0;
}
<div class="main">
<div class="line">
<input class="input" />
</div>
</div>
Here I am expecting that when the view appears the initial input is of size 2rem (padding, margin, border do not matter here) and when you start typing and exceeds the size it grows till it reach the size of main. Any suggestions how I can achieve that?
An example using only CSS and the contenteditable attribute:
.main {
display: flex;
}
.line {
display: flex;
}
.input {
border: 1px solid lightslategray;
padding: 0.5em;
margin: 1em;
min-width: 30ch;
max-width: 100%;
}
<div class="main">
<div class="line">
<p class="input" contenteditable></p>
</div>
</div>
Here is another solution using the .getBoundingClientRect(), so the idea is to add the text of the input to a p element calculate the width of it then set it as the width of the input, this keeps using the same input instead of content editable trick that a user can press enter and have multiple lines, also can be used in forms...
var txtElement = document.querySelector("#hidden-text");
document.querySelector(".input").oninput = function() {
txtElement.innerHTML = this.value;
var width = txtElement.getBoundingClientRect().width;
this.style.width = width < 100 ? 100 : width + "px";
};
.input {
width: 100px;
}
#hidden-text {
display: inline-block;
position: absolute;
visibility: hidden;
}
#hidden-text, .input {
font-size: 16px;
font-family: Serif;
}
<div class="main">
<div class="line">
<input class="input"/>
</div>
</div>
<p id="hidden-text"></p>
Probably not the most efficient solution, but you could do something like this:
document.querySelector('.input').addEventListener('input', function(e) {
let span = document.createElement('span');
span.innerHTML = e.target.value;
span.style.visibility = 'hidden';
span.style.fontSize = '15px';
document.body.appendChild(span);
if (span.offsetWidth > e.target.offsetWidth - 10) {
e.target.style.width = span.offsetWidth + 'px';
}
span.parentNode.removeChild(span);
});
.main {
width: 100%;
display: flex;
}
.line {
min-width: 2rem;
display: flex;
}
.input{
flex: 1 1 auto;
min-width: 0;
}
<div class="main">
<div class="line">
<input class="input"/>
</div>
</div>

Categories