Convert jQuery to JavaScript - mousemove - javascript

I am trying to convert this jQuery Code into Vanilla JavaScript code. I'm having trouble with some of the methods. I think I have some of them, but some of them not.
Jquery:
jQuery('.image').click(function() {
jQuery(this).toggleClass('normal-zoom zoom-in');
});
jQuery('.image').on('mousemove', function(event) {
var bbox = event.target.getBoundingClientRect();
var mouseX = event.clientX - bbox.left;
var mouseY = event.clientY - bbox.top;
var xPercent = (mouseX / bbox.width) * 100;
var yPercent = (mouseY / bbox.height) * 100;
jQuery(this).css('transform-origin', (xPercent+'% ' + yPercent+ '%') );
});
jQuery('.image').on('mouseenter', function() {
jQuery(this).addClass('zoom-in');
jQuery(this).removeClass('normal-zoom');
});
jQuery('.image').on('mouseleave', function() {
jQuery(this).addClass('normal-zoom');
jQuery(this).removeClass('zoom-in');
});
I tried.
Javascript:
document.querySelector('.image').onclick = function() {
document.querySelector(this).classList.toggle('normal-zoom zoom-in');
};
document.querySelector('.image').addEventListener('mousemove', function(event) {
var bbox = event.target.getBoundingClientRect();
var mouseX = event.clientX - bbox.left;
var mouseY = event.clientY - bbox.top;
var xPercent = (mouseX / bbox.width) * 100;
var yPercent = (mouseY / bbox.height) * 100;
document.querySelector(this).css('transform-origin', (xPercent+'% ' + yPercent+ '%') );
});
document.querySelector('.image').addEventListener('mouseenter', function() {
document.querySelector(this).classList.add('zoom-in');
document.querySelector(this).classList.remove('normal-zoom');
});
document.querySelector('.image').addEventListener('mouseleave', function() {
document.querySelector(this).classList.add('normal-zoom');
document.querySelector(this).classList.remove('zoom-in');
});
Where is the error?

I have added two comments to the code to show two lines I fixed and why they needed fixing.
Additionally, I replaced every instance of document.querySelector(this) with document.querySelector('.image'), because the callbacks inside .onclick and .addEventListener do not bind this to the selected element the same way JQuery does, so you need to re-select the element each time. In your code, this is referencing the callback function, which is not what you want.
document.querySelector('.image').onclick = function() {
document.querySelector('.image').classList.toggle('zoom-in');// I split this line into two lines, because `.toggle()` can only accept one classname at a time.
document.querySelector('.image').classList.toggle('normal-zoom');
};
document.querySelector('.image').addEventListener('mousemove', function(event) {
var bbox = event.target.getBoundingClientRect();
var mouseX = event.clientX - bbox.left;
var mouseY = event.clientY - bbox.top;
var xPercent = (mouseX / bbox.width) * 100;
var yPercent = (mouseY / bbox.height) * 100;
document.querySelector('.image').style.transformOrigin = xPercent+'% ' + yPercent+'%';// There is no such `.css()` method on DOM nodes. Instead, set an element's css by using the `style` property.
});
document.querySelector('.image').addEventListener('mouseenter', function() {
document.querySelector('.image').classList.add('zoom-in');
document.querySelector('.image').classList.remove('normal-zoom');
});
document.querySelector('.image').addEventListener('mouseleave', function() {
document.querySelector('.image').classList.add('normal-zoom');
document.querySelector('.image').classList.remove('zoom-in');
});
I would recommend using this code instead though, as it's cleaner, easier to read, implements DRY practices, and works to prevent bugs related to changes in the DOM.
const imageElement = document.querySelector('.image');
imageElement.addEventListener('click', function() {
imageElement.classList.toggle('zoom-in');
imageElement.classList.toggle('normal-zoom');
};
imageElement.addEventListener('mousemove', function(event) {
const bbox = imageElement.getBoundingClientRect();
const mouseX = event.clientX - bbox.left;
const mouseY = event.clientY - bbox.top;
const xPercent = (mouseX / bbox.width) * 100;
const yPercent = (mouseY / bbox.height) * 100;
imageElement.style.transformOrigin = xPercent+'% ' + yPercent+'%';
});
imageElement.addEventListener('mouseenter', function() {
imageElement.classList.add('zoom-in');
imageElement.classList.remove('normal-zoom');
});
imageElement.addEventListener('mouseleave', function() {
imageElement.classList.add('normal-zoom');
imageElement.classList.remove('zoom-in');
});

Related

AddEventListener to current target

i'm trying to add some mouse movement to a background image within elements in a grid -
this is my HTML, its repeated multiple times:
<div class="pure-u-1-3 grid-item" >
<div class="bg-img" style="background:url('images/blog/network.png'"></div>
<div class="blogInner" >
<p>SOME TEXT</p>
Read More
</div>
</div>
the following code works - but moves all elements -
const bg = document.querySelector('.bg-img');
const bgIn = document.querySelector('.blogInner');
const windowWidth = window.innerWidth / 5;
const windowHeight = window.innerHeight / 5 ;
bgIn.addEventListener('mousemove', (e) => {
const mouseX = e.clientX / windowWidth;
const mouseY = e.clientY / windowHeight;
bg.style.transform = `translate3d(-${mouseX}%, -${mouseY}%, 0)`;
});
I have tried to make the above code rso that it runs only on the hovered item as follows -
$('.grid-item').mouseover(function(event) {
const thisitem = $(event.currentTarget);
const bg = $(event.currentTarget).find('.bg-img');
const bgIn = $(event.currentTarget).find('.blogInner');
const windowWidth = window.innerWidth / 5;
const windowHeight = window.innerHeight / 5 ;
bgIn.addEventListener('mousemove', (e) => {
const mouseX = e.clientX / windowWidth;
const mouseY = e.clientY / windowHeight;
bg.style.transform = `translate3d(-${mouseX}%, -${mouseY}%, 0)`;
});
});
on hover i get the error:
bgIn.removeEventListener is not a function
I'm completely stumped - as the same code oustide the hover function works fine - can anyone help me understand whats going wrong please?
If you just use jquery events it should work rather than mixing native js with jquery.
bgIn.mousemove((e) => {
const mouseX = e.clientX / windowWidth;
const mouseY = e.clientY / windowHeight;
bg.css({transform: `translate3d(-${mouseX}%, -${mouseY}%, 0)`});
});

Adding decimals to rangeslider

This is the function I'm using for making the range slider:
function rangeSlider(id, onDrag) {
var range = document.getElementById(id),
dragger = range.children[0],
draggerWidth = 20, // width of your dragger
down = false,
rangeWidth, rangeLeft;
dragger.style.width = draggerWidth + 'px';
dragger.style.left = -draggerWidth + 'px';
dragger.style.marginLeft = (draggerWidth / 2) + 'px';
range.addEventListener("mousedown", function(e) {
rangeWidth = this.offsetWidth;
rangeLeft = this.offsetLeft;
down = true;
updateDragger(e);
return false;
});
document.addEventListener("mousemove", function(e) {
updateDragger(e);
});
document.addEventListener("mouseup", function() {
down = false;
});
function updateDragger(e) {
if (down && e.pageX >= rangeLeft && e.pageX <= (rangeLeft + rangeWidth)) {
dragger.style.left = e.pageX - rangeLeft - draggerWidth + 'px';
if (typeof onDrag == "function") onDrag(Math.round(((e.pageX - rangeLeft) / rangeWidth) * 100));
}
}
}
// Run!
rangeSlider('range-slider-1', function(value) {
document.getElementById('test-result').innerHTML = value + '%';
});
rangeSlider('range-slider-2', function(value) {
document.getElementById('test-result').innerHTML = value + '%';
});
JSBIN: http://jsbin.com/yuvekecodo/edit?html,js,output
How can I have the output in decimals?
For example if I set the range from 10 - 100 I want it to be able to have the decimals. 10.01, 10.02, 10.03 ~ 99.97. 99.98, 99.99, etc.
What is the best way to achieve this?
Thanks guys, I'm loosing my mind over this for days.
Cheers.
Thanksl
Please try this may help to get 2 digit decimal point values:
if (typeof onDrag == "function") onDrag(parseFloat(((e.pageX - rangeLeft) / rangeWidth) * 100).toFixed(2));
Use it for like:
function updateDragger(e) {
if (down && e.pageX >= rangeLeft && e.pageX <= (rangeLeft + rangeWidth)) {
dragger.style.left = e.pageX - rangeLeft - draggerWidth + 'px';
var startpnt=10,endpnt=50,baseval_percent,baseval;
baseval_percent = ((e.pageX - rangeLeft) / rangeWidth) * 100;
baseval = (endpnt-startpnt)*baseval_percent/100;
baseval = baseval+startpnt;
if (typeof onDrag == "function") onDrag(parseFloat(baseval).toFixed(2));
}
}

select specific area of a div

I made a carousel using 2 divs named "left" and "right" putting mousemove events on them. I wanted to make it go up and down as well so I created a "top" and "bottom" and noticed that I couldn't make them combine to go the way the cursor goes.
I thus thought of targeting a specific area in the container (i.e top half of my container div) instead of creating divs inside triggering a specific direction, this way (I think) I can trigger all these event altogether. However after now hours of research I couldn't find a way to do so.
How should I proceed ? here is the code : http://jsfiddle.net/pool4/vL5g3/3/
var x=0,
y=0,
rateX=0,
rateY=0,
maxspeed=10;
var backdrop = $('.backdrop');
$('.directionx', backdrop).mousemove(function(e){
var $this = $(this);
var left = $this.is('.left');
var right = $this.is('.right');
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
});
$('.directiony', backdrop).mousemove(function(e){
var $this = $(this);
var top = $this.is('.top');
var bottom = $this.is('.bottom');
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
backdrop.hover(
function(){
var scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
},
function(){
var scroller = $(this).data('scroller');
clearInterval( scroller );
}
);
function moveBackdrop(){
x += maxspeed * rateX;
y += maxspeed * rateY;
var newpos = x+'px '+y+'px';
backdrop.css('background-position',newpos);
}
Your problem is that the divs that control movement up and down are placed over the ones that control left and right, so the latter do not receive the mousemove event ever. Mouse events do not propagate through layers, even if they're transparent. I changed your code and CSS, so each div is in one of the corners. To make things easier, I've used data-* attributes so the direction controlled by each div is set in a declarative way, without the need to change the code. You'll see that the code is much simpler (and it could be simplified even more).
By the way, you could achieve this witout extra divs, just controlling where the cursor is (to the top, right, left or bottom of the center of the div).
backdrop.on('mousemove', '.dir', function(e){
var $this = $(this);
var direction = $(e.target).attr('data-direction');
var left = direction.indexOf('left') > - 1;
var right = direction.indexOf('right') > - 1;
var top = direction.indexOf('up') > - 1;
var bottom = direction.indexOf('down') > - 1;
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
I've updated your fiddle.
EDIT In this new fiddle I do it without extra divs:
var w = backdrop.width() / 2;
var h = backdrop.height() / 2;
var center = {
x: backdrop.offset().left + backdrop.width() / 2,
y: backdrop.offset().top + backdrop.height() / 2
};
backdrop.on('mousemove', function(e){
var offsetX = e.pageX - center.x;
var offsetY = e.pageY - center.y;
rateX = -offsetX / w;
rateY = -offsetY / h;
});
backdrop.hover(
function(){
var scroller = $(this).data('scroller');
if (!scroller) {
scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
}
},
function(){
var scroller = $(this).data('scroller');
if (scroller) {
clearInterval( scroller );
$(this).data('scroller', null);
}
}
);
As you see, the mousmove handler is considerably simpler.
To avoid issue of children losing event could use just the one.
First HTML from 4 child divs to just one
<div class="backdrop">
<div class="direction"></div>
</div>
<div id="pos"></div>
Next Inside the mousemove find your relative position
//Get Relative Position
var relX = e.pageX - $this.offset().left;
var relY = e.pageY - $this.offset().top;
Get Relative Position as a percentage of width and put 50% of it in negative for direction
var w = $this.width();
rateX = ((relX / w) - 0.5) * -1;
var h = $this.height();
rateY = ((relY / h) - 0.5) * -1;
Fiddle

Stop function when pressing ctrl jQuery

So I am making a little game where you have to press Ctrl to stop a div from jumping randomly.
However I can't get it working...
The jumpRandom function works fine, until i put the randomJump(){return false;}; inside the if (event.ctrlKey) {}. What should I do to get it working?
js:
$(document).ready(function() {
function randomFromTo(from, to){
return Math.floor(Math.random() * (to - from + 1) + from);
}
$( "#goal" ).bind('mouseenter keypress', function(event) {
if (event.ctrlKey) {
randomJump(){return false;};
}
});
$('#goal').mouseenter(randomJump);
function randomJump(){
/* get Window position and size
* -- access method : cPos.top and cPos.left*/
var cPos = $('#pageWrap').offset();
var cHeight = $(window).height() - $('header').height() - $('footer').height();
var cWidth = $(window).width();
// get box padding (assume all padding have same value)
var pad = parseInt($('#goal').css('padding-top').replace('px', ''));
// get movable box size
var bHeight = $('#goal').height();
var bWidth = $('#goal').width();
// set maximum position
maxY = cPos.top + cHeight - bHeight - pad;
maxX = cPos.left + cWidth - bWidth - pad;
// set minimum position
minY = cPos.top + pad;
minX = cPos.left + pad;
// set new position
newY = randomFromTo(minY, maxY);
newX = randomFromTo(minX, maxX);
$('#goal').fadeOut(50, function(){
$('#goal').fadeIn(700);
});
$('#goal').animate({
left: newX,
top: newY,
duration: 500
});
}
});
Try this:
$("#goal").bind('mouseenter keypress', function (e) {
randomJump(e);
});
function randomJump(e) {
if (!e.ctrlKey) {
//do normal stuff
} else {
//depending on how permanent you need this to be...
//$("#goal").unbind('mouseenter keypress');
}
return !e.ctrlKey;
}

This javascript fails on mouseover

can anyone figure out why this JavaScript won't work? It correctly generates the document.write output, but when you try to drag it it starts complaining about top and left not being set. any idea whats wrong?
abilitynames=new Array('Heal','Slash','Stab','Poison Slash','Knockout','','','','Tornado','','','','','','','','Icespike','','','','','','','','Bolt','Jumping Bolt','','','','','','','Roast','Burn','','','','','','','Earthquake','Rockwall','','','','','','','Kill','Deflect','Anti-Heal','','','','','','Backslash','Darkwall','Steal','Take','','','','');
abilitytypes=new Array(3,1,1,1,1,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,3,2,2,2,2,2,1,2,3,3,2,2,2,2);
abilitycolors=new Array('#00FF00','#FFFFFF','#0000FF','#FFFF00','#FF0000','#AD6C00','#AD00FF','#000000');
for(i=0;i<64;i++){
document.write("<div onmousedown='dragging=this.id;this.style.position=\"fixed\";this.style.zIndex=1000;this.style.left=event.clientX-75;this.style.top=event.clientY-15;' onmouseout='if(dragging===this.id){this.style.left=event.clientX-75;this.style.top=event.clientY-15;}' onmousemove='if(dragging===this.id){this.style.left=event.clientX-75;this.style.top=event.clientY-15;}' onmouseup='dragging=false;if(event.clientX<450||event.clientY>"+(180+(abilitytypes[i]*90))+"||event.clientY<"+(100+((abilitytypes[i]-1)*(90*abilitytypes[i])/((4%abilitytypes[i])+1)))+"){this.style.position=\"relative\";this.style.top=0;this.style.left=0;this.style.zIndex=0;}else{this.style.left=460;this.style.top=(Math.round((event.clientY-30)/45)*45)+15;if(abilitys[Math.round((event.clientY-120)/45)]!=\"\"&&abilitys[Math.round((event.clientY-120)/45)]!=this.id){document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.position=\"relative\";document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.left=0;document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.top=0;}abilitys[Math.round((event.clientY-120)/45)]=this.id;alert(abilitys);}' id='"+i+"' class='abilityblock"+abilitytypes[i]+"'><div class='abilityicon' style='background-position:"+(Math.floor(i/8)*-20)+"px "+((i%8)*-20)+"px;'></div><div class='abilityname' style='color:"+abilitycolors[Math.floor(i/8)]+";'>"+abilitynames[i]+"</div></div>");
}
I've probably broken the script just TRYING to clean up this unholy mess and simplifying things a little, but at least it seems to be a bit more readable now (not including the array definitions):
<script type="text/javascript">
var dragging;
function mouseDown(el) {
dragging = el.id;
el.style.position = "fixed";
el.style.zIndex = 1000;
el.style.left = event.clientX - 75;
el.style.top = event.clientY-15;
}
function mouseOut(el) {
if (dragging === el.id) {
el.style.left = event.clientX - 75;
el.style.top = event.clientY - 15;
}
}
function mouseMove(el) {
if (dragging === el.id) {
el.style.left = event.clientX - 75;
el.style.top = event.clientY - 15;
}
}
function mouseUp(el, i) {
dragging = false;
if ( (event.clientX < 450) ||
(event.clientY > (180 + (abilitytypes[i] * 90)) ) ||
(event.clientY < (100 + (abilitytypes[i] - 1) * (90 * abilitytypes[i]) / ((4 % abilitytypes[i]) + 1)))) {
el.style.position = "relative";
el.style.top = 0;
el.style.left = 0;
el.style.zIndex = 0;
} else {
el.style.left = 460;
el.style.top = (Math.round((event.clientY - 30) / 45) * 45) + 15;
if ((abilitys[Math.round((event.clientY - 120) / 45)] != "") && (abilitys[Math.round((event.clientY - 120) / 45)] != el.id)) {
var subel = document.getElementById(abilitys[Math.round((event.clientY-120)/45)]);
subel.style.position="relative";
subel.style.left=0;
subel.style.top=0;
}
abilitys[Math.round((event.clientY - 120) / 45)] = el.id;
alert(abilitys);
}
}
for(var i = 0; i < 64; i++){
document.write("
<div onmousedown='mouseDown(this);'
onmouseout='mouseOut(this);'
onmousemove='mouseMove(el);'
onmouseup='mouseUp(this, i);'
id='"+i+"'
class='abilityblock"+abilitytypes[i]+"'>
<div class='abilityicon' style='background-position:"+(Math.floor(i/8)*-20)+"px "+((i%8)*-20)+"px;'></div>
<div class='abilityname' style='color:"+abilitycolors[Math.floor(i/8)]+";'>"+abilitynames[i]+"</div>
</div>");
}
</script>
Phew. And after all that, I'm guessing your missing 'left' and 'top' parameters are because your dynamically computed element IDs are generating non-existent IDs in the mouseup handler.
My suggestion? Scrap this home-brew drag 'n drop stuff and use the functionality provided by Mootools or jQuery. Far less trouble, especially when having to deal with cross-browser differences.
Searching your code, you haven't defined an onmouseover event. You define onmousedown, onmouseout, onmousemove, and onmouseup. No onmouseover.

Categories