I have this script, and it does exactly what I want. shows and hides a div and follows mouse-cursor around and does it only when viewport is a certain size and above, but I would like to know how to condense it so the whole script is not duplicated twice, one for on load and one for when listening to browser window resizing.
<script>
$( document ).ready(function() { //document ready
$( window ).on( "load", function() { //entire page has loaded
if ($(window).width() < 963) {
tip = $(this).nextAll('#tail');
tip.hide();
}
else {
//Tooltips
$("#mainbody").hover(function(){
tip = $(this).nextAll('#tail');
tip.show(); //Show tooltip
}, function() {
tip.hide(); //Hide tooltip
}).mousemove(function(e) {
if ($(window).width() > 962) {
//Change these numbers to move the tooltip offset
var mousex = e.pageX + 20; //Get X coodrinates
var mousey = e.pageY + 20; //Get Y coordinates
var tipWidth = tip.width(); //Find width of tooltip
var tipHeight = tip.height(); //Find height of tooltip
//Distance of element from the right edge of viewport
var tipVisX = $(window).width() - (mousex + tipWidth);
//Distance of element from the bottom of viewport
//var tipVisY = $(window).height() - (mousey + tipHeight);
var tipVisY = $("#mainbody").height() - (tipHeight);
if (tipVisX < 1) { //If tooltip exceeds the X coordinate of viewport
//mousex = e.pageX - tipWidth - 20;
} if (tipVisY < 1) { //If tooltip exceeds the Y coordinate of viewport
//mousey = e.pageY - tipHeight - 20;
}
//Absolute position the tooltip according to mouse position
tip.css({ top: mousey, left: mousex });
}
});
}
$( window ).resize(function() {
if ($(window).width() < 963) {
tip = $(this).nextAll('#tail');
tip.hide();
}
else {
//Tooltips
$("#mainbody").hover(function(){
tip = $(this).nextAll('#tail');
tip.show(); //Show tooltip
}, function() {
tip.hide(); //Hide tooltip
}).mousemove(function(e) {
if ($(window).width() > 962) {
//Change these numbers to move the tooltip offset
var mousex = e.pageX + 20; //Get X coodrinates
var mousey = e.pageY + 20; //Get Y coordinates
var tipWidth = tip.width(); //Find width of tooltip
var tipHeight = tip.height(); //Find height of tooltip
//Distance of element from the right edge of viewport
var tipVisX = $(window).width() - (mousex + tipWidth);
//Distance of element from the bottom of viewport
//var tipVisY = $(window).height() - (mousey + tipHeight);
var tipVisY = $("#mainbody").height() - (tipHeight);
if (tipVisX < 1) { //If tooltip exceeds the X coordinate of viewport
//mousex = e.pageX - tipWidth - 20;
} if (tipVisY < 1) { //If tooltip exceeds the Y coordinate of viewport
//mousey = e.pageY - tipHeight - 20;
}
//Absolute position the tooltip according to mouse position
tip.css({ top: mousey, left: mousex });
}
});
}
});
});
});
</script>
You can insert code to function and call this function where you want.
$( document ).ready(function() { //document ready
$( window ).on( "load", function() { //entire page has loaded
change(this)
$( window ).resize(function() {
change(this)
});
});
});
function change(_this){
if ($(window).width() < 963) {
tip = $(_this).nextAll('#tail');
tip.hide();
}
else {
//Tooltips
$("#mainbody").hover(function(){
tip = $(this).nextAll('#tail');
tip.show(); //Show tooltip
}, function() {
tip.hide(); //Hide tooltip
}).mousemove(function(e) {
if ($(window).width() > 962) {
//Change these numbers to move the tooltip offset
var mousex = e.pageX + 20; //Get X coodrinates
var mousey = e.pageY + 20; //Get Y coordinates
var tipWidth = tip.width(); //Find width of tooltip
var tipHeight = tip.height(); //Find height of tooltip
//Distance of element from the right edge of viewport
var tipVisX = $(window).width() - (mousex + tipWidth);
//Distance of element from the bottom of viewport
//var tipVisY = $(window).height() - (mousey + tipHeight);
var tipVisY = $("#mainbody").height() - (tipHeight);
if (tipVisX < 1) { //If tooltip exceeds the X coordinate of viewport
//mousex = e.pageX - tipWidth - 20;
} if (tipVisY < 1) { //If tooltip exceeds the Y coordinate of viewport
//mousey = e.pageY - tipHeight - 20;
}
//Absolute position the tooltip according to mouse position
tip.css({ top: mousey, left: mousex });
}
});
}
}
An alternative is to manually fire the event handler using .trigger('[eventname]'):
$( window ).on( "load", function() {
$( window ).resize(function() {
//do some stuff
}).trigger('resize');
});
Related
I am looking for a way to resize individually several div on a page (like a browser window, that you can resize from a bottom corner), keeping the same proportions/ratio. I made the code work for a class .handle and .dragger, but all the div with the same class are being modified at the same time, while I would like it to be executed only for the div we click on.
Here is the code to resize that I'm working with:
$(".handle").bind('mousedown', draggerDown);
$("body").bind('mouseup', draggerUp);
function calculateNewSize(size) {
// {currHeight, currWidth, newHeight, newWidth, offsetX, offsetY}
var newWidth;
var newHeight;
if (Math.abs(size.offsetX) > Math.abs(size.offsetY)) {
newWidth = size.currWidth + size.offsetX;
newHeight = newWidth * (size.currHeight / size.currWidth);
} else {
newHeight = size.currHeight + size.offsetY;
newWidth = newHeight * (size.currWidth / size.currHeight);
}
return {
"height": newHeight,
"width": newWidth
};
}
function draggerDown() {
event.stopPropagation();
event.preventDefault();
currentX = event.pageX;
currentY = event.pageY;
currentHeight = $(".dragger").height();
currentWidth = $(".dragger").width();
$("body").bind('mousemove', draggerMove);
}
function draggerMove() {
var draggerElements = document.getElementsByClassName("dragger");
for (var n = 0; n < draggerElements.length; ++n) {
var targetStyle = window.getComputedStyle(draggerElements[n], null);
var newHeight = currentHeight + (event.pageY - currentY);
var newWidth = currentWidth + (event.pageX - currentX);
// AT THIS POINT, THE LOGIC COMES IN.
// CUSTOMIZE 'calculateNewSize' function above
var newSize = calculateNewSize({
"currHeight": currentHeight,
"currWidth": currentWidth,
"newHeight": newHeight,
"newWidth": newWidth,
"offsetX": (event.pageX - currentX),
"offsetY": (event.pageY - currentY)
});
currentHeight = newSize.height;
currentWidth = newSize.width;
newHeight = newSize.height;
newWidth = newSize.width;
// AT THIS POINT, THE LOGIC IS DONE.
// SIZES SHOULD BE COOL NOW
$(".dragger").css("height", newHeight + "px");
$(".dragger").css("width", newWidth + "px");
console.log($(".dragger").height());
currentX = event.pageX;
currentY = event.pageY;
}
}
function draggerUp() {
$("body").unbind('mousemove');
}
// tell the embed parent frame the height of the content
if (window.parent && window.parent.parent){
window.parent.parent.postMessage(["resultsFrame", {
height: document.body.getBoundingClientRect().height,
slug: "xUAZ5"
}], "*")
}
// always overwrite window.name, in case users try to set it manually
window.name = "result"
}
I am trying to do it with that methodology (from another project) but I don't really know if it could work with the previous code:
var u;
for(var i=1; i<13; i++) {
var specificClass= document.getElementsByClassName("class"+i);
for (u = 0; u < specificClass.length; u++) {
specificClass[u].addEventListener("click", thefunction);
}
}
function thefunction(evenement) {
// alert(evenement.target.classList)
var clickedElement = document.getElementsByClassName(evenement.target.classList);
for (u = 0; u < clickedElement.length; u++) {
clickedElement[u].style etc.
}
}
In that case I would these two groups of class: handle1, handle2, handle3,... and dragger1, dragger2, dragger3...
Here is my simplified html body:
<div class="draggableDiv dragger div1">
<div class="handle"></div>
</div>
<div class="draggableDiv dragger div2">
<div class="handle"></div>
</div>
Any other methodology is very welcomed of course, this is only what I've been trying :)
Let me know if you would need more details
Thanks!
Trying to capture the position of click on an image (marked as x for end users). But on window resize the 'X' position changes. Is something I am missing in my code, how can i maintain the position in portrait and landscape modes
<script>
$("#_img").on("click",function(event){
var X = event.pageX-5, Y = event.pageY-5;
$("#marker").css({
"left":X,
"right":Y
}).show();
});
</script>
<img id="_img" src="car.png" width="550px" height="168px"/>
<div id="_mrk" style="display:none;">x</div>
You have to update position of 'x' everytime window resized or orientation changed and image should be in perentage instead of pixels
var width = 0;
var height = 0;
$("#_img").on("click", function(event) {
var X = event.pageX,
Y = event.pageY;
$("#_mrk").css({
"left": X,
"top": Y
}).show();
width = $("#_img").width();
height = $("#_img").height();
});
function getNewValue(posValue, oldImgPos, newImgPos) {
return posValue * (newImgPos / oldImgPos);
}
$(window).resize(function() {
var newx = getNewValue($('#_mrk').offset().left, width, $("#_img").width());
$("#_mrk").css("left", newx);
var newy = getNewValue($('#_mrk').offset().top, height, $("#_img").height());
$("#_mrk").css("top", newy);
width = $("#_img").width();
height = $("#_img").height();
});
#_mrk {
position: absolute;
}
#_img {
width: 100%;
}
<img id="_img" src="http://clipartion.com/wp-content/uploads/2015/11/colorable-car-line-art-free-clip-art.png" width="550px" height="168px" />
<div id="_mrk" style="display:none;">x</div>
Save value of document width when img is clicked. Add event listener to resize event and change X and Y values when it fired:
var X, Y, doc_width, a_ratio;
$("#_img").on("click", function(event){
X = event.pageX-5;
Y = event.pageY-5;
doc_width = document.documentElement.clientWidth;
a_ratio = $(this).width()/$(this).height();
move_mark(X, Y);
});
$(window).on("resize", function(){
var x = X + (document.documentElement.clientWidth - doc_width);
var y = Y + (x - X)/a_ratio;
move_mark(x, y);
})
function move_mark(X,Y){
$("#marker").css({
"left":X,
"right":Y
}).show();
}
You can use percentage instead of pixels to support all sizes.
First of all make sure the container of the img and the marker is position relative, and the marker is position absolute.
Then, when clicking you will need to calculate the X and Y within the image, and then based on that calculate percentage.
var img = $("#_img");
img.on("click", function(event){
var x = event.pageX - this.offsetLeft;
var y = event.pageY - this.offsetTop;
var left = 'calc(' + ((x / img.width()) * 100) + '% - 5px)';
var right = 'calc(' + ((y / img.height()) * 100) + '% - 5px)';
$("#marker").css({
"left": left,
"right": right
}).show();
});
I am trying to get Jquery UI Sortable working with the zoom. The issue is the mouse doesn't move with the same speed as the element you are dragging. There are quite a few examples posted about how to get this working with Draggable. Here is a example of the workaround for Draggable items:
http://jsfiddle.net/TqUeS/660/
var zoom = $('#canvas').css('zoom');
var canvasHeight = $('#canvas').height();
var canvasWidth = $('#canvas').width();
$('.dragme').draggable({
drag: function(evt,ui)
{
// zoom fix
ui.position.top = Math.round(ui.position.top / zoom);
ui.position.left = Math.round(ui.position.left / zoom);
// don't let draggable to get outside of the canvas
if (ui.position.left < 0)
ui.position.left = 0;
if (ui.position.left + $(this).width() > canvasWidth)
ui.position.left = canvasWidth - $(this).width();
if (ui.position.top < 0)
ui.position.top = 0;
if (ui.position.top + $(this).height() > canvasHeight)
ui.position.top = canvasHeight - $(this).height();
}
});
I would expect the Drag event to be replaced by the Sort event in the Sortable version of this, but as you can see from the below fiddle, it doesn't work. Setting ui.position in the sort event has no effect - it seems to set it and discard it after the event fires.
http://jsfiddle.net/TqUeS/658/
var zoom = $('#canvas').css('zoom');
var canvasHeight = $('#canvas').height();
var canvasWidth = $('#canvas').width();
$('#canvas').sortable({
items: "div",
sort: function(evt,ui)
{
// zoom fix
ui.position.top = Math.round(ui.position.top / zoom);
ui.position.left = Math.round(ui.position.left / zoom);
// don't let draggable to get outside of the canvas
if (ui.position.left < 0)
ui.position.left = 0;
if (ui.position.left + $(this).width() > canvasWidth)
ui.position.left = canvasWidth - $(this).width();
if (ui.position.top < 0)
ui.position.top = 0;
if (ui.position.top + $(this).height() > canvasHeight)
ui.position.top = canvasHeight - $(this).height();
}
});
If anyone has another workaround, I'd be happy to hear it.
Minor differences between draggable and sortable. In sort, the ui.helper is the item and position does not effect it in the same way, it's just a report of it's position.
For Draggable, in drag for ui.position, it states:
Current CSS position of the helper as { top, left } object. The values may be changed to modify where the element will be positioned. This is useful for custom containment, snapping, etc.
For Sortable, in sort for ui.position, it states:
The current position of the helper represented as { top, left }.
Try this:
Example: http://jsfiddle.net/Twisty/4nv60ob9/2/
HTML
<div id="canvas" data-zoom="0.5">
<div class="dragme"></div>
<div class="dragme"></div>
<div class="dragme"></div>
</div>
<div id="report"></div>
JavaScript
var zoom = $("#canvas").data("zoom");
console.log(typeof zoom, zoom.toString());
var canvasHeight = $('#canvas').height();
var canvasWidth = $('#canvas').width();
$('#canvas').sortable({
items: "div",
start: function(e, ui) {
console.log("Sort Start Triggered");
},
sort: function(evt, ui) {
console.log("Sort Triggered");
// zoom fix
ui.position.top = Math.round(ui.position.top / zoom);
ui.position.left = Math.round(ui.position.left / zoom);
$("#report").html("Top: " + ui.position.top + " Left: " + ui.position.left);
// don't let draggable to get outside of the canvas
if (ui.position.left < 0) {
ui.helper.css("left", 0);
}
if (ui.position.left + ui.helper.width() > canvasWidth) {
ui.helper.css("left", (canvasWidth - ui.helper.width()) + "px");
}
if (ui.position.top < 0) {
ui.helper.css("top", 0);
}
if (ui.position.top + ui.helper.height() > canvasHeight) {
ui.helper.css("top", (canvasHeight - ui.helper.height()) + "px");
}
$("#report").html("Top: " + (canvasHeight - ui.helper.height()) + " Left: " + (canvasWidth - ui.helper.width()));
}
});
I think that is working in the same way.
I'm trying to get the position of a click inside a div so that when I position a window as the mouse drag moves it, the mouse cursor will be exactly on the spot (relative to the moving window) where the initial click occurred.
Here's the window:
<div id="PopUp" class="Popup">
<div id="PopUpTitleBar"><img class="xOut" onclick="ClosePopUp();" src="/images/xOut.png"></div>
<div class="InnerPopup">
<!-- <p>Here is the body of a pop up element.</p> -->
<p id="PopUpBody"></p>
</div>
</div>
And I have these methods to handle the clicking and dragging:
var firstClick = true;
var offsetX = 0;
var offsetY = 0;
function mouseUp()
{
window.removeEventListener('mousemove', divMove, true);
firstClick = true;
}
function mouseDown(e){
window.addEventListener('mousemove', divMove, true);
}
function divMove(e){
var div = document.getElementById('PopUp');
if (firstClick == true) {
offsetX = $('#PopUpTitleBar').offset().left;
offsetY = $('#PopUpTitleBar').offset().top;
firstClick = false;
}
var spotX = e.pageX - offsetX;
var spotY = e.pageY - offsetY;
div.style.top = spotY + 'px';
div.style.left = spotX + 'px';
}
This sorta works, except that my offsetX and offsetY are returning the position of the top left corner of PopUpTitleBar instead of the position of the click within PopUpTitleBar.
How can I correct this so my offsets are relative to the inside top left corner of PopUpTitleBar?
Thanks.
You have the click position on the screen. And then you have the position of the div. Substract the main position with the div position and youll have the finger position relative to that div.
$('#PopUpTitleBar').click(function (e) {
var posX = $(this).offset().left, posY = $(this).offset().top;
alert("e.pageX: " + e.pageX + " posX:" + posX + " e.pageY:" + e.pageY + " posY:" + posY);
});
To get the value of the Position of click within div use the event e parameter in your callback.
function divMove(e){
var div = document.getElementById('PopUp');
if (firstClick == true) {
// use $(e).target
offsetX = $( $(e).target ).offset().left;
offsetY = $( $(e).target ).offset().top;
firstClick = false;
}
var spotX = e.pageX - offsetX;
var spotY = e.pageY - offsetY;
div.style.top = spotY + 'px';
div.style.left = spotX + 'px';
}
This is what ultimately worked:
function divMove(e){
var div = document.getElementById('PopUp');
var titleBar = document.getElementById('PopUpTitleBar');
if (firstClick == true) {
offsetX = e.pageX - $('#PopUpTitleBar').offset().left;
offsetY = e.pageY - $('#PopUpTitleBar').offset().top;
firstClick = false;
}
var spotX = e.pageX - offsetX;
var spotY = e.pageY - offsetY;
div.style.top = spotY + 'px';
div.style.left = spotX + 'px';
}
First, I calculate the position in the titlebar by subtracting the top left corner of the title bar from the point at which the first click occurred. Then, as the mouse moves, the subsequent positions of the mouse must all subtract that offset so that the top left corner remains the same distance from the original click. Thanks everyone for the suggestions - they helped me wrap my head around the problem better.
I have a dynamic div, and I want to know when the mouse is hover this div. I tryed with .is( ':hover' ) but doesn't work.
jsFiddle demo
In the demo I have made a moving div and if I doesn't move the mouse the log is never called, but if I put manually the mouse hover the box it write always the logs.
Never writes the log in the console.
Always writes the log in the console, even the box is gone.
It's a bug or I have made a mistake? How can I detect the hover properly?
You should be tracking the mouse movement with the mousemove() event and check the last known position of the mouse on the movement of the div.
Example:
HTML & CSS:
.red-box {
display : inline-block;
position : absolute;
width : 50px;
height : 50px;
top : 10px;
left : 0px;
background-color : red;
}
#wrapper {
height: 100vh;
width: 100vw;
}
<div id="wrapper">
<div class="red-box"></div>
</div>
JavaScript:
var posX = 0;
var step = 10;
var maxX = 200;
var mouseX = -1;
var mouseY = -1;
var entered = false;
var $box = $('.red-box');
setInterval(function () {
posX += step;
if (posX >= maxX)
posX = 0;
$box.css("left", posX);
var top = $box.offset().top;
if (mouseX >= posX && mouseX <= (posX + $box.width()) && mouseY >= top && mouseY <= (top + $box.height())) {
console.log("mouse entered");
entered = true;
} else if (entered) {
console.log("mouse left");
entered = false;
}
}, 500);
$("#wrapper").on("mousemove", function (e) {
mouseX = e.pageX - $(this).position().left;
mouseY = e.pageY - $(this).position().top;
}).on("mouseleave", function()
{
mouseX = -1;
mouseY = -1;
});
FIDDLE
Edit: Added a new mouseleave() event to the wrapper.