Calculate text width without rounding using Javascript - javascript

I have a div that I using Javascript to change the position of. However, it is rounding incorrectly.
#hi{
background-color: blue;
width: 2px;
height: 10px;
position: absolute;
}
<div id = "hi"></div>
<button onclick="myFunction()" style = "margin-top: 100px">Click me</button>
<script>
function myFunction() {
var div = document.getElementById("hi");
div.style.left = "0px";
console.log("BEFORE: " + div.style.left);
var moveBy = 109.8125;
div.style.left = moveBy + 'px';
console.log("MOVE BY: " + moveBy);
console.log("NEW POSITION: " + div.style.left);
}
</script>
It should move it by 109.8125, but instead moves it by 109.813.
Any way to make it more accurate and move it to 109.8125?
It may seem like it is not that important, but I am doing this several times, so then it looks in the wrong place, relative to other elements.

If you really need to prevent precision drift due to rounding error, I'd suggest you keep track of the value independently of the style attribute. Here's an example of how you could do it using a data attribute:
function myFunction() {
var div = document.getElementById("hi");
div.style.left = "0px";
console.log("BEFORE: " + div.style.left);
var moveBy = 109.8125;
// track the current value as a data attribute,
// which won't get rounded
const left = div.dataset.left = parseFloat(div.dataset.left || 0) + moveBy;
// apply the computed value as a style
div.style.left = left + 'px';
console.clear();
console.log(`dataset.left: ${left}, style.left: ${div.style.left}`);
}
#hi {
background-color: blue;
width: 2px;
height: 10px;
position: absolute;
}
<div id="hi"></div>
<button onclick="myFunction()" style="margin-top: 100px">Click me</button>

Related

Find position of multiple draggable elements

How would i be able to find the top, left, bottom and right position of multiple moveable elements on a page? I tried jQuery .position() for it, however the function gives me the position of only the most recent moveable element created (div). Here's the code -
Finding Position -
$(document).on('click', function(e) {
var createdWindow = $(nWindow).position();
var createdWindow_right = $(nWindow).position().left + $(nWindow).width();
var createdWindow_bottom = $(nWindow).position().top + $(nWindow).height();
console.log("Top position: " + createdWindow.top + ", Left position: " + createdWindow.left + ", right position: " + createdWindow_right + ", bottom position: " + createdWindow_bottom);
// returns an object with x/y coordinates of the top-left corner of the element
});
Div Creation -
function windowProperties(containment,x,y,width,height){ //New Window Style and jQuery Functions
$(containment).append('<div id="window'+divCount+'"><p id="para'+divCount+'">Drop Here</p></div>');
nWindow = document.getElementById('window'+divCount);
paragraph = document.getElementById('para'+divCount);
paragraph.style.color = "black";
paragraph.style.fontSize = "20px";
paragraph.style.fontWeight = "bold";
paragraph.style.padding = "10px";
paragraph.style.textAlign = "center";
nWindow.style.width = width+"px"; //680
nWindow.style.position = "absolute";
nWindow.style.height = height+"px"; //294.75
nWindow.style.opacity = "0.5";
nWindow.style.background = "white";
nWindow.style.zIndex = "200";
nWindow.style.top = x+"px";
nWindow.style.left = y+"px";
};
Use draggable event property of an element and send event on drag events.
For Example:-
<div draggable = true ondragstart="abc(event)>
//some HTML CODE
</div>
<script>
function abc(event)
{
console.log(event) // here in this event you get all the data of draggable elements
}
</script>
Consider the following example.
$(function() {
$.fn.getPosition = function() {
var results = $(this).position();
results.right = results.left + $(this).width();
results.bottom = results.top + $(this).height();
return results;
}
$(".drag").draggable({
containment: "parent",
stop: function(e, ui) {
console.log($(this).attr("id"), $(this).getPosition());
}
});
});
.cnt {
width: 340px;
height: 340px;
border: 1px solid black;
}
.drag {
width: 20px;
height: 20px;
background: #ccc;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="cnt">
<div class="drag" id="box-1"></div>
<div class="drag" id="box-2"></div>
</div>
This creates a function that can get you the full position. You can then use that in stop callback for a Drag action.

Loop for onmousemove event

I've run into a problem with running a loop to trigger a mousemove event on my HTML/CSS.
I know I can go through and get every individual ID on the HTML tags to execute the code the way I want. But I know there is a better way to do it with a loop of some sort and use far less code.
The images should follow the mouse while moving over the div with class mycard. Any suggestions or ideas on how to get it working properly would be very much appreciated.
I've tried running a loop to add the classes to divs but had no luck.
var mouseHover = document.getElementById('moveHover');
window.onmousemove = function(e) {
var x = e.clientX;
var y = e.clientY;
mouseHover.style.top = (y + 20) + 'px';
mouseHover.style.left = (x + 20) + 'px';
};
.mycard span {
position: absolute;
display: none;
z-index: 99;
}
.mycard:hover span {
display: block;
position: fixed;
overflow: hidden;
}
.imgHover a {
position: relative;
}
.imgHover span {
position: absolute;
display: none;
z-index: 99;
}
.imgHover a:hover span {
display: block;
position: fixed;
overflow: hidden;
}
<div class="imgHover mycard">
<div class="cardcost">
<p class="cardcosttext">2</p>
</div>
<div class="hscardepic">
<a style="margin-left: 1000%;vertical-align: middle;">
Doomsayer
<span id="moveHover">
<img src="Classic_Set/doomsayer.png" height="300" width="300" />
</span>
</a>
</div>
<div class="cardamount">
<p class="cardamounttext">×2</p>
</div>
</div>
If I understand what you're asking, you could use querySelectorAll to get the elements and forEach to move them:
// get the div that responds to mouse movement
const mycard = document.querySelector('.mycard');
// add a mousemove listener
mycard.addEventListener('mousemove', function(e) {
// get the DOM element with the mousemove listener from the event
const {target} = e;
// get img child elements of the target.
// (use whatever css selector you need here. doesn't have to img)
const images = target.querySelectorAll('img');
// iterate over each item...
images.forEach(image => {
// ...and do whatever you need to do with it
const x = e.clientX;
const y = e.clientY;
image.style.top = (y + 20) + 'px';
image.style.left = (x + 20) + 'px';
})
});
I'm also not entirely sure what your end-goal is, but I'll take a stab at it.
I would recommend changing moveHover to being the class instead of the ID. Then you could do something like this:
var mouseHover = null;
window.onmousemove = function (e) {
if(mouseHover != null){
var x = e.clientX;
var y = e.clientY;
mouseHover.style.top = (y+20) + 'px';
mouseHover.style.left = (x+20) + 'px';
}
};
function onHover(e){
mouseHover = e.target.querySelector('.moveHover');
}
var elements = document.getElementsByClassName('imgHover');
for(var i = 0; i < elements.length; i++){
elements[i].onmouseenter = onHover;
}
The loop runs one time to set the onmouseenter event. Sure beats moving all .moveHover elements all the time.

how to make a stimulus (image, div, whichever's easiest) show up on right or left half of screen randomly using javascript

how to make a stimulus (image, div, whichever's easiest) show up on right or left half of screen randomly using javascript.
Any ideas about having the button clicks record the reaction time, which button is clicked (left or right), and which side the stimulus was presented on?? Also, the left button should be "true" when stimulus is presented on the right and vice versa.
<head>
<style >
.divStyleLeft {
width: 300px;
height: 300px;
background-color: lightblue;
float: left;
}
.divStyleRight {
width: 300px;
height: 300px;
background-color: lightgreen;
float: right;
}
.maxWidth {
width: 100%;
}
.button {
float: right;
}
.button2 {
float: left;
}
</style>
</head>
<body onload="presentStimulus()">
<div class="button">
<button onclick="presentStimulus()">Click Me</button>
</div>
<div class="button2">
<button onclick="presentStimulus()">Click Me </button>
</div>
<div class="maxwidth"></div>
<div id="float" class="divStyleLeft" onclick="recordClick()">
I AM NOT FLOATING
</div>
<script>
let numClicks= 0;
let timeStart = 0;
let timeEnd = 0;
function Trial(trialTime, sidePresented,buttonClicked,) {
this.trialTime = trialTime;
this.sidePresented= sidePresented;
this.buttonClicked= buttonClicked;
}
let allTrials = [];
for(x = 0; x < 12; x++)
allTrials.push(new Trial(0,0,0));
Trial.prototype.toString=function(){
return this.trialTime + "ms, Side : " + this.sidePresented + ", Reaction Time: " + this.buttonClicked
+ "<br>";
};
function presentStimulus() {
const elem = document.querySelector ( '#float' );
const min = 1;
const max = 2;
const v = Math.floor(Math.random() * (max - min + 1)) + min;
console.log ( 'Random num is ' + v + ": ", '1 will go left, 2 will go right' );
v === 1 ?
( () => {
elem.classList = [ 'divStyleLeft' ];
elem.innerText = 'Hello!';
} ) () :
( () =>{
elem.classList = [ 'divStyleRight' ];
elem.innerText = 'Hi!';
} ) ();
}
function recordClick()
{
let theData = document.getElementById("#float").data;
timeEnd = Date.now();
allTrials[numClicks].trialTime = timeEnd - timeStart;
allTrials[numClicks].sidePresented = theData.sidePresented;
allTrials[numClicks].buttonClicked = theData.buttonClicked;
if (numClicks < 11) {
numClicks++;
presentStimulus();
}
else {
document.getElementById("float").style.visibility = "hidden";
let output = "";
for (x = 0; x < allTrials.length; x++)
output = output + "<b>:" + (x + 1) + "</b>:" + allTrials[x].toString();
document.getElementById("display").innerHTML = output;
}
}
</script>
<p id="display"></p>
</body>
There's a bunch of ways you could go about this.
If you're using plain 'ol JS, I'd probably create classes in CSS that float left or right, possibly appear as a flex container that displays left or right, whatever your specific need might be (again, there's a lot of ways to go about it, and one might be better than the other given your context).
When you've determined left or right (gen a random number or whatever), update the classlist on the DOM elements with the desired class to make it go this way or that.
For what it's worth, here's a bare-bones vanilla JS example. Again, I don't know your specific context, but this should give you a start on how to look at it. Floating may not be ideal, you may want to just hide/show containers that already exist on the left or right or actually create whole new DIVs and insert them into known "holder" containers (usually just empty divs), but the idea is the same; gen the random number, alter the classlists of the elements you want to hide/show/move/whatever, and if necessary, alter the innerHTML or text as needed.
<html>
<head>
<style>
.divStyleLeft {
width: 300px;
height: 300px;
background-color: lightblue;
float: left;
}
.divStyleRight {
width: 300px;
height: 300px;
background-color: lightgreen;
float: right;
}
.maxWidth {
width: 100%;
}
</style>
</head>
<body>
<button onclick="onClick()">Click Me</button>
<div class="maxwidth">
<div id="floater" class="divStyleLeft">
I AM NOT FLOATING
</div>
<div>
<script>
function onClick () {
const elem = document.querySelector ( '#floater' );
const min = 1;
const max = 2;
const v = Math.floor(Math.random() * (max - min + 1)) + min;
console.log ( 'Random num is ' + v + ": ", '1 will go left, 2 will go right' );
v === 1 ?
( () => {
elem.classList = [ 'divStyleLeft' ];
elem.innerText = 'I am floating LEFT';
} ) () :
( () =>{
elem.classList = [ 'divStyleRight' ];
elem.innerText = 'I am floating RIGHT';
} ) ();
}
</script>
</body>
</html>

Javascript won't put array values in CSS syntax

I'm trying to make a slide show using multiple background-images and using the background-position property to animate them. Here is the code:
HTML:
<div class="slide_holder" id="slide_holder"></div>
CSS:
.slide_holder {
float: left;
width: 1440px;
height: 720px;
background-image: url("images/gc-h-s-01.jpg"), url("images/gc-h-s-02.jpg"), url("images/gc-h-s-03.jpg");
background-repeat: no-repeat;
background-size: 100%;
background-position: 0px, 1440px, 2880px;
transition: 1s;
}
JS:
var imageIndex = 1;
var x;
var PosValues = ["0px, 1440px, 2880px", "-1440px, 0px, 1440px", "-2880px, -1440px, 0px"]
startSlides();
function startSlides() {
x = setInterval(IncAndWrite, 1000);
}
function IncAndWrite() {
var i;
document.getElementById("slide_holder").style.backgroundPosition = PosValues[imageIndex];
imageIndex++;
if (imageIndex > 2) {imageIndex = 0;}
}
The concept is that the background-position values for each background-image change every 1s keeping only one image in the visible frame.
The above mentioned code works just fine, but I do not want to write individual position values for different screen sizes (as my website is responsive). So I wrote the following code:
JS:
var imageIndex = 1;
var x;
var UnitRes = 1440;
var PosValues = [
UnitRes*0 + "px, " + UnitRes*1 + "px, " + UnitRes*2 + "px;",
UnitRes*(-1) + "px, " + UnitRes*0 + "px, " + UnitRes*1 + "px;",
UnitRes*(-2) + "px, " + UnitRes*(-1) + "px, " + UnitRes*0 + "px;"]
startSlides();
function startSlides() {
x = setInterval(IncAndWrite, 1000);
}
function IncAndWrite() {
var i;
document.getElementById("slide_holder").style.backgroundPosition = PosValues[imageIndex];
imageIndex++;
if (imageIndex > 2) {imageIndex = 0;}
}
The basic concept is that you put the width of the container in UnitRes and then the values get calculated. But this does not seem to work. The background-position values don't change at all.
What I thought was causing the problem:
In the second case of js code I'm putting a variable value inside an array which I thought is not being converted to a string type while inputing it in the CSS syntax.
What I tried doing:
I used typeof but it is showing the type as string
Then I tried using:
document.getElementById("slide_holder").style.backgroundPosition = PosValues[imageIndex].valueOf();
but still it's not working. I also used alert(PosValues[imageIndex]); to check if the values are ok and they are.
Please help me.
The problem was that in first time you have defined parameters without semicolon ; and in second example you have placed it what broke the script.

adding two .height() 's together? Jquery

I'm trying to add two .height()'s together in order to get a responsive number for my onScroll event how do I add two of these together?
I'm general, I'm just trying to get the animation to fire after getting to the bottom of everything above the element. Is there any other way to do that besides just adding the heights of everything above?
window.addEventListener('load', function() {
$(window).scroll(function() {
var eventScroll = window.pageYOffset;
var eventScrollAmount = ($("#sectionOneImage").height() + $("#bannerOne").height());
if( eventScroll > eventScrollAmount) {
$("#sectionOneImage").addClass("animated slideInLeft ");
}
else {
$("#sectionOneImage").removeClass("animated slideInLeft ");
}
});
});
Here's an example of how to grab two heights using vanilla JS.
var sizeOfOne = document.getElementById('one').offsetHeight;
var sizeOfTwo = document.getElementById('two').offsetHeight;
document.getElementById('hook').innerHTML = 'The first div is ' + sizeOfOne + ' pixels in height, the second div is ' + sizeOfTwo + ' pixels in height. The total size of both div\'s are ' + (sizeOfOne + sizeOfTwo) + ' pixels.';
#one {
height: 50px;
background: red;
}
#two {
height: 75px;
background: blue;
}
<div id="hook"></div>
<div id="one"></div>
<div id="two"></div>

Categories

Resources