Resetting xpos on mouseup / touchup events - html

I have a issue after a lengthy battle with simply assigning the touch events to a image slider.
I now have a working touchscreen image slider but the only problem is that when I touchscreen the movement position begins from the center of the div and moves the whole div to be positioned with the pointer in the middle and lift off screen - and then attempt to do another movement. The movement position begins again in the center of the div.
I know I need to reset the co-ords somehow when I lift off screen, or maybe unbind, but I have no idea how to do this.
Here is a little HTML for the divs:
.container{
position:absolute;
top:0%;
left:0%;
width:500px;
height:100%;
}
.drag{
position: absolute;
top:1%;
left:0%;
width:100%;
height:15%;
-webkit-transform: translate3d(0,0,0);
border-style: solid; 2px;
border-color: blue;
z-index:1000;
}
</head>
<body>
<div id="container" class="container">
<div id='drag' class='drag'><!---video area--->
some images
</div>
</div>
Here is the code for the swipe events.
var dom = {
container: document.getElementById("container"),
drag: document.getElementById("drag"),
}
var container = {
x: dom.container.getBoundingClientRect().left,
y: dom.container.getBoundingClientRect().top,
w: dom.container.getBoundingClientRect().width,
h: dom.container.getBoundingClientRect().height
}
var drag = {
w: dom.drag.offsetWidth
}
target = null;
document.body.addEventListener('touchstart', handleTouchStart, false);
document.body.addEventListener('touchmove', handleTouchMove, false);
document.body.addEventListener('touchend', handleTouchEnd, false);
document.body.addEventListener('touchcancel', handleTouchCancel, false);
function handleTouchStart(e) {
if (e.touches.length == 1) {
var touch = e.touches[0];
target = touch.target;
}
}
function handleTouchMove(e) {
if (e.touches.length == 1) {
if(target === dom.drag) {
moveDrag(e);
}
}
}
function handleTouchEnd(e) {
if (e.touches.length == 0) { // User just took last finger off screen
target = null;
}
}
function handleTouchCancel(e) {
return;
}
function moveDrag(e) {
var touch = e.touches[0];
var posX = touch.pageX - container.x - drag.w / 2;
dom.drag.style.left = posX + "px";
}

Related

Sticky footer after complete scroll

I am trying to create a "see-also" button that is located on the bottom of the page.
When the user reaches the bottom and decides to scroll back up, I want it to stick to the bottom of the viewport.
I have been trying with position:sticky but then it is already sticked to the bottom of the viewport when the page just loaded. I only want this after a complete scroll down.
Any clues?
Thanks in advance.
This is an example with javascript (see result sticky button on scroll top
const DIRECTION_BOTTOM = 1;
const DIRECTION_TOP = 0;
let previousScroll = 0;
let direction = scrollY === 0 ? DIRECTION_BOTTOM : DIRECTION_TOP;
window.addEventListener('scroll', function(){
const scrollY = window.scrollY;
if(direction === DIRECTION_TOP && previousScroll < scrollY){
direction = DIRECTION_BOTTOM;
// remove sticky
document.getElementById("sticky").classList.remove("show");
}
else if(direction === DIRECTION_BOTTOM && previousScroll > scrollY ){
direction = DIRECTION_TOP;
// Add sticky
document.getElementById("sticky").classList.add("show");
}
previousScroll = scrollY;
})
You can create this functionality with JQuery by creating a function which calculates when an element is in the viewport. If the button enters the viewport, add a class which makes the element position: sticky. There are different ways to approach this problem but one solution is something like this:
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
$(window).on("scroll", function() {
if($('#button').isInViewport()) {
$('#button').addClass('sticky');
}
});
body {
text-align: center;
}
.button {
padding: 6px 12px;
}
.div {
width: 100%;
height: 250px;
color: #fff;
}
.div1 {
background: blue;
}
.div2 {
background: red;
}
.div3 {
background: purple;
}
.sticky {
position: sticky;
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
height: 100%;
bottom: 5px;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<div class="div div1">Filler div 1</div>
<div class="div div2">Filler div 2</div>
<div class="div div3">Filler div 3</div>
<button type="button" class="button" id="button">See Also</button>
Scrambled everything together and this is working now:
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
document.getElementById("see-also").classList.add("sticky");
}
};
Thanks you everyone

dragleave event is firing on inner childs

I am trying to use HTML5 drag and drop and make the dropable container to change its style when the draggable element is over it.
the problem is if the dropable container contain inner elements a dragleave events getting fired making the container to lose its style.
as you can see when the draggable element is getting inside the small green box. we lose the red border of the outside div.
<html>
<head>
<style>
.droptarget {
width: 100px;
height: 100px;
margin: 15px;
margin-right: 100px;
padding: 10px;
border: 1px solid #aaaaaa;
}
.inner-droptarget {
margin-left: 20px;
margin-top: 20px;
width: 50px;
height: 50px;
border: 1px solid green
}
</style>
</head>
<body>
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget">Drag me!</p>
<div class="droptarget" ondragenter="dragEnter(event)" ondragleave="dragLeave(event)" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="inner-droptarget">
</div>
</div>
<script>
function dragStart(event) {
event.dataTransfer.setData("Text", event.target.id);
}
function dragEnter(event) {
if ( event.target.className == "droptarget" ) {
event.target.style.border = "3px dotted red";
}
}
function dragLeave(event) {
if ( event.target.className == "droptarget" ) {
event.target.style.border = "";
}
}
</script>
<p>
The border of the outside div should remain red even if dragging into the green div!
</p>
</body>
</html>
You have to ignore "dragleave" events that are fired on elements that are contained in "droptarget" (for example "inner-droptarget").
To do so, you can detect if the event was fired from a descendant of the drop area. Your handler will look like this:
function dragLeave(event) {
if ( event.target.className == "droptarget" ) && !($('.droptarget').contains(event.fromElement) {
event.target.style.border = "";
}
}
When you enter the inner div during dragging, the event drag enter and then drag leave event is firing. We need a way to mark that you are leaving the outer div and entering the inner div so the border stays red on the outer div.
I can get both borders to be red, but when you leave its a similar problem, both borders go back to green.
<body>
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget">Drag me!</p>
<div id="myOuterDiv" class="droptarget" ondragenter="dragEnter1(event)"
ondragleave="dragLeave1(event)"
ondrop="drop(event)"
ondragover="allowDrop(event)">
<div id="myInnerDiv" class="inner-droptarget" ondragenter="dragEnter2(event)"
ondragleave="dragLeave2(event)">
</div>
</div>
<script>
var inOuter = false;
var inInner = false;
function dragStart(event) {
event.dataTransfer.setData("Text", event.target.id);
}
function dragEnter1(event) {
inOuter = true;
document.getElementById("myInnerDiv").addEventListener("ondragenter", dragEnter2);
console.log("entered outer");
return highlightBorder();
}
function dragLeave1(event) {
console.log("left outer");
inOuter = false;
highlightBorder();
event.preventDefault();
}
function dragEnter2(event) {
console.log("entered inner");
inInner = true;
inOuter = true;
return highlightBorder();
}
function dragLeave2(event) {
console.log("left inner");
inInner = false;
inOuter = true;
return highlightBorder();
}
function allowDrop(ev) {
return false;
}
function drop(event) {
var inOuter = false;
var inInner = false;
document.getElementById("myInnerDiv").style.border ="3px solid green";
document.getElementById("myOuterDiv").style.border ="3px solid green";
return false;
}
function highlightBorder() {
if( inInner)
{
document.getElementById("myInnerDiv").style.border ="3px dotted red";
document.getElementById("myOuterDiv").style.border ="3px dotted red";
return false;
}
if(!inInner && inOuter)
{
document.getElementById("myInnerDiv").style.border ="";
document.getElementById("myOuterDiv").style.border ="3px dotted red";
return false;
}
if(!inInner && !inOuter)
{
document.getElementById("myInnerDiv").style.border ="";
document.getElementById("myOuterDiv").style.border ="";
return false;
}
}
</script>
<p>
The border of the outside div should remain red even if dragging into the green div!
</p>
</body>
</html>
You can use a counter to solve the problem.When dragenter counter++,when dragleave counter-- and check counter === 0 then do something.
// div has an child element
divEl.addEventListen("dragenter",dragEnter)
divEl.addEventListen("dragleave",dragLeave)
counter = 0
function dragEnter(){
counter++
}
function dragLeave(){
counter--
if(counter === 0){
// then do something
}
}

Zooming a particular part of image

How to make Zooming effect like these, when hovering the image Sample Image
$(document).ready(function(){
var native_width = 0;
var native_height = 0;
//Now the mousemove function
$(".magnify").mousemove(function(e){
//When the user hovers on the image, the script will first calculate
//the native dimensions if they don't exist. Only after the native dimensions
//are available, the script will show the zoomed version.
if(!native_width && !native_height)
{
//This will create a new image object with the same image as that in .small
//We cannot directly get the dimensions from .small because of the
//width specified to 200px in the html. To get the actual dimensions we have
//created this image object.
var image_object = new Image();
image_object.src = $(".small").attr("src");
//This code is wrapped in the .load function which is important.
//width and height of the object would return 0 if accessed before
//the image gets loaded.
native_width = image_object.width;
native_height = image_object.height;
}
else
{
//x/y coordinates of the mouse
//This is the position of .magnify with respect to the document.
var magnify_offset = $(this).offset();
//We will deduct the positions of .magnify from the mouse positions with
//respect to the document to get the mouse positions with respect to the
//container(.magnify)
var mx = e.pageX - magnify_offset.left;
var my = e.pageY - magnify_offset.top;
//Finally the code to fade out the glass if the mouse is outside the container
if(mx < $(this).width() && my < $(this).height() && mx > 0 && my > 0)
{
$(".large").fadeIn(100);
}
else
{
$(".large").fadeOut(100);
}
if($(".large").is(":visible"))
{
//The background position of .large will be changed according to the position
//of the mouse over the .small image. So we will get the ratio of the pixel
//under the mouse pointer with respect to the image and use that to position the
//large image inside the magnifying glass
var rx = Math.round(mx/$(".small").width()*native_width - $(".large").width()/2)*-1;
var ry = Math.round(my/$(".small").height()*native_height - $(".large").height()/2)*-1;
var bgp = rx + "px " + ry + "px";
//Time to move the magnifying glass with the mouse
var px = mx - $(".large").width()/2;
var py = my - $(".large").height()/2;
//Now the glass moves with the mouse
//The logic is to deduct half of the glass's width and height from the
//mouse coordinates to place it with its center at the mouse coordinates
//If you hover on the image now, you should see the magnifying glass in action
$(".large").css({left: px, top: py, backgroundPosition: bgp});
}
}
})
})
/*Some CSS*/
* {margin: 0; padding: 0;}
.magnify {width: 200px; margin: 50px auto; position: relative;}
/*Lets create the magnifying glass*/
.large {
width: 175px; height: 175px;
position: absolute;
border-radius: 100%;
/*Multiple box shadows to achieve the glass effect*/
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85),
0 0 7px 7px rgba(0, 0, 0, 0.25),
inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
/*Lets load up the large image first*/
background: url('http://thecodeplayer.com/uploads/media/iphone.jpg') no-repeat;
/*hide the glass by default*/
display: none;
}
/*To solve overlap bug at the edges during magnification*/
.small { display: block; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Lets make a simple image magnifier -->
<div class="magnify">
<!-- This is the magnifying glass which will contain the original/large version -->
<div class="large"></div>
<!-- This is the small image -->
<img class="small" src="http://thecodeplayer.com/uploads/media/iphone.jpg" width="200"/>
</div>
<!-- Lets load up prefixfree to handle CSS3 vendor prefixes -->
<script src="http://thecodeplayer.com/uploads/js/prefixfree.js" type="text/javascript"></script>
<!-- You can download it from http://leaverou.github.com/prefixfree/ -->
<!-- Time for jquery action -->
<script src="http://thecodeplayer.com/uploads/js/jquery-1.7.1.min.js" type="text/javascript"></script>
Try this one
(function ($) {
$(document).ready(function() {
$('.xzoom, .xzoom-gallery').xzoom({zoomWidth: 400, title: true, tint: '#333', Xoffset: 15});
$('.xzoom2, .xzoom-gallery2').xzoom({position: '#xzoom2-id', tint: '#ffa200'});
$('.xzoom3, .xzoom-gallery3').xzoom({position: 'lens', lensShape: 'circle', sourceClass: 'xzoom-hidden'});
$('.xzoom4, .xzoom-gallery4').xzoom({tint: '#006699', Xoffset: 15});
$('.xzoom5, .xzoom-gallery5').xzoom({tint: '#006699', Xoffset: 15});
//Integration with hammer.js
var isTouchSupported = 'ontouchstart' in window;
if (isTouchSupported) {
//If touch device
$('.xzoom, .xzoom2, .xzoom3, .xzoom4, .xzoom5').each(function(){
var xzoom = $(this).data('xzoom');
xzoom.eventunbind();
});
$('.xzoom, .xzoom2, .xzoom3').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
xzoom.eventleave = function(element) {
element.hammer().on('tap', function(event) {
xzoom.closezoom();
});
}
xzoom.openzoom(event);
});
});
$('.xzoom4').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
var counter = 0;
xzoom.eventclick = function(element) {
element.hammer().on('tap', function() {
counter++;
if (counter == 1) setTimeout(openfancy,300);
event.gesture.preventDefault();
});
}
function openfancy() {
if (counter == 2) {
xzoom.closezoom();
$.fancybox.open(xzoom.gallery().cgallery);
} else {
xzoom.closezoom();
}
counter = 0;
}
xzoom.openzoom(event);
});
});
$('.xzoom5').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
var counter = 0;
xzoom.eventclick = function(element) {
element.hammer().on('tap', function() {
counter++;
if (counter == 1) setTimeout(openmagnific,300);
event.gesture.preventDefault();
});
}
function openmagnific() {
if (counter == 2) {
xzoom.closezoom();
var gallery = xzoom.gallery().cgallery;
var i, images = new Array();
for (i in gallery) {
images[i] = {src: gallery[i]};
}
$.magnificPopup.open({items: images, type:'image', gallery: {enabled: true}});
} else {
xzoom.closezoom();
}
counter = 0;
}
xzoom.openzoom(event);
});
});
} else {
//If not touch device
//Integration with fancybox plugin
$('#xzoom-fancy').bind('click', function(event) {
var xzoom = $(this).data('xzoom');
xzoom.closezoom();
$.fancybox.open(xzoom.gallery().cgallery, {padding: 0, helpers: {overlay: {locked: false}}});
event.preventDefault();
});
//Integration with magnific popup plugin
$('#xzoom-magnific').bind('click', function(event) {
var xzoom = $(this).data('xzoom');
xzoom.closezoom();
var gallery = xzoom.gallery().cgallery;
var i, images = new Array();
for (i in gallery) {
images[i] = {src: gallery[i]};
}
$.magnificPopup.open({items: images, type:'image', gallery: {enabled: true}});
event.preventDefault();
});
}
});
})(jQuery);
<link href="https://unpkg.com/xzoom#1.0.7/dist/xzoom.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-2.1.1.js"></script>
<script src="https://unpkg.com/xzoom#1.0.7/dist/xzoom.min.js"></script>
<script src="https://hammerjs.github.io/dist/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/js/foundation.min.js"></script>
<body>
<div class="container">
<!-- default start -->
<section id="default" class="padding-top0">
<div class="row">
<div class="large-12 column"><h3>Product Zooming</h3></div>
<hr>
<div class="large-5 column">
<div class="xzoom-container">
<img class="xzoom" id="xzoom-default" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/01_b_car.jpg" xoriginal="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/original/01_b_car.jpg" />
<div class="xzoom-thumbs">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/thumbs/01_b_car.jpg" xpreview="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/01_b_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/02_o_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/03_r_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/04_g_car.jpg" title="The description goes here">
</div>
</div>
</div>
<div class="large-7 column"></div>
</div>
</section>
<!-- default end -->
</div>
</body>

Hover not working with text below image in anchor tag html

I have this code for making a nav bar. I am trying to add image buttons with text below them. The problem is that the images can be of different sizes and thus they are not centered properly in the output.
Also, the title for all images must come at same level but its not the case.
ul.nav-icon {
list-style: none;
display: block;
margin: auto;
width: 800px;
}
ul.nav-icon li {
float: left;
}
ul.nav-icon a {
display: inline-block;
text-decoration: none;
}
ul.nav-icon a:hover {
background: #4095A6;
}
ul.nav-icon img {
margin: 0px 0px 0px 0px;
padding-top: 16px;
padding-left: 30px;
}
.img-box {
width: 160px;
height: 138px;
}
h6 {
color: white;
text-align: center;
}
<ul class="nav-icon">
<li>
<a href="#" class="img-box">
<img src="http://imgur.com/Et4vXHk.png">
<h6>Families</h6>
</a>
</li>
<li>
<a href="#" class="img-box">
<img src="http://i.imgur.com/lubEbTP.png">
<h6>Families</h6>
</a>
</li>
<li>
<a href="#" class="img-box">
<img src="http://i.imgur.com/lubEbTP.png">
<h6>Families</h6>
</a>
</li>
</ul>
Here's a way to deal with your problem: https://github.com/smohadjer/sameHeight
Here's the .js file you'll need to include in your html. It's better if it's an external file. For any confusion, this file can also be found in the link above with both minified/unminified versions.
;(function ($, window, document, undefined) {
'use strict';
var pluginName = 'sameHeight',
defaults = {
oneHeightForAll: false,
useCSSHeight: false
};
//private method
var getHeightOfTallest = function(elms) {
var height = 0;
$.each(elms, function() {
var _h = $(this).outerHeight();
if (_h > height) {
height = _h;
}
});
return height;
};
// The actual plugin constructor
function Plugin(element, options) {
this.$element = $(element);
this.options = $.extend({}, defaults, options);
this.init();
}
// methods
var methods = {
init: function() {
var self = this;
self.index = 0;
self.$elms = self.$element.children();
self.cssProperty = self.options.useCSSHeight ? 'height' : 'min-height';
$(window).on('resize.' + pluginName, function() {
//remove previously set height or min-height
self.$elms.css(self.cssProperty, '');
initSameHeight();
});
//use setTimeout to make sure any code in stack is executed before
//calculating height
setTimeout(function() {
initSameHeight();
}, 0);
function initSameHeight() {
//if there are adjacent elements
if (self.getRow(0).length > 1) {
self.setMinHeight(0);
if (self.options.callback) {
self.options.callback();
}
}
}
},
setMinHeight: function(index){
var self = this;
var row = self.options.oneHeightForAll ? self.$elms : self.getRow(index);
var height = getHeightOfTallest(row);
$.each(row, function() {
$(this).css(self.cssProperty, height);
});
if (!self.options.oneHeightForAll && self.index < self.$elms.length - 1) {
self.setMinHeight(self.index);
}
},
getRow: function(index) {
var self = this;
var row = [];
var $first = self.$elms.eq(index);
var top = $first.position().top;
row.push($first);
self.$elms.slice(index + 1).each(function() {
var $elm = $(this);
if ($elm.position().top === top) {
row.push($elm);
self.index = $elm.index();
} else {
self.index = $elm.index();
return false;
}
});
return row;
},
destroy: function() {
var self = this;
//remove event handlers
$(window).off('resize.' + pluginName);
//remove dom changes
self.$elms.css(self.cssProperty, '');
self.$element.removeData('plugin_' + pluginName);
}
};
// build
$.extend(Plugin.prototype, methods);
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function(options) {
this.each(function() {
if(!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
return this;
};
})(jQuery, window, document);
After you include the above .js file, add this script to your current page:
$('.img-box').sameHeight();
This should make all of your boxes with image/text be the same size height wise.
Next in order to make sure the text is always at a certain point within your img-box, add some css inline, or make a class with the css as
h6 {
bottom:10px;
}
The amount of pixels can be anything you'd like it to be. To explain, the text will now always be 10 pixels from the bottom of the img-box.
Either this, or just make the images the background image for the container and set them all to predetermined sizes.

How can I check the pixel location of my cursor?

On any given application, is there a way, maybe in dev tools where I can check the pixel location of my mouse hover?
Use javascript to get cursor location.
document.addEventListener("mouseover", function( event ) {
console.log(event.screenX, event.screenY);
}, false);
Getting the Mouse Click Position :
<!DOCTYPE html>
<html>
<head>
<title>Move to Click Position</title>
<style type="text/css">
body {
background-color: #FFF;
margin: 30px;
margin-top: 10px;
}
#contentContainer {
width: 550px;
height: 350px;
border: 5px black solid;
overflow: hidden;
background-color: #F2F2F2;
cursor: pointer;
}
#thing {
position: relative;
left: 50px;
top: 50px;
transition: left .5s ease-in, top .5s ease-in;
}
</style>
</head>
<body>
<div id="contentContainer">
<img id="thing" src="//www.kirupa.com/images/smiley_red.png">
</div>
<script src="//www.kirupa.com/prefixfree.min.js"></script>
<script>
var theThing = document.querySelector("#thing");
var container = document.querySelector("#contentContainer");
container.addEventListener("click", getClickPosition, false);
function getClickPosition(e) {
var parentPosition = getPosition(e.currentTarget);
var xPosition = e.clientX - parentPosition.x - (theThing.clientWidth / 2);
var yPosition = e.clientY - parentPosition.y - (theThing.clientHeight / 2);
theThing.style.left = xPosition + "px";
theThing.style.top = yPosition + "px";
}
// Helper function to get an element's exact position
function getPosition(el) {
var xPos = 0;
var yPos = 0;
while (el) {
if (el.tagName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft);
yPos += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: xPos,
y: yPos
};
}
</script>
</body>
</html>
Refer : MouseEvent clientX Property & Getting the Mouse Click Position