I'm using the following code to allow users to resize a DIV element vertically, but when the click and drag the handle, text and other elements on the page get selected as if the user was just clicking and highlighting everything on the page. Is there a way to prevent this from happening as this looks very bad? This is being used with Prototype.js.
function DragCorner(container, handle) {
var container = $(container);
var handle = $(handle);
// Add property to container to store position variables
container.moveposition = {y:0};
function moveListener(event) {
// Calculate how far the mouse moved
var moved = { y:(container.moveposition.y - event.pointerY()) };
// Reset container's x/y utility property
container.moveposition = {y:event.pointerY()};
// Update container's size
var size = container.getDimensions();
container.setStyle({height: size.height + moved.y + 'px'});
}
// Listen for 'mouse down' on handle to start the move listener
handle.observe('mousedown', function(event) {
// Set starting x/y
container.moveposition = {y:event.pointerY()};
// Start listening for mouse move on body
Event.observe(document.body,'mousemove',moveListener);
});
// Listen for 'mouse up' to cancel 'move' listener
Event.observe(document.body,'mouseup', function(event) {
Event.stopObserving(document.body,'mousemove',moveListener);
console.log('stop listening');
});
}
Following up your earlier question and answer, add a small handle element and make it as the only element that can be selected and draggable. Also I guess you made that div's position as relative and handle position as absolute. Right??
Adding the following to the DIV fixed this:
onselectstart="return false;"
Related
I have a jQuery var that sits within an .on('scroll') method. The var is detecting the top position of a div, that has a position of absolute. However, on scroll, the position changes to fixed, which results in the value changing (which I do not want), instead, I want to lock in the original value of the variable.
So, for example, if fixedTop has an initial value of 500, how can I lock that value in, regardless of the fact that the value changes on scroll due to it having a position of fixed?
Thanks.
$(window).on('load scroll resize', function() {
// Vars
var fixed = $('.mydiv');
var fixedTop = fixed.offset().top;
}
Simply move those variables OUTSIDE of the scroll listener and remove the load event from the event listener also.
$(document).ready(function(){
var fixed = $('.mydiv');
var fixedTop = fixed.offset().top;
$(window).on('scroll resize', function() {
console.log(fixed, fixedTop)
});
});
I am currently working on a custom resize functionality which will allow the user to drag the vertical border between two divs to resize their widths in respect to each other. I am accomplishing this by creating an invisible third div that has a width of 10px with a resize cursor and sits on top of the border between the two elements. When the user clicks on the invisible 3rd div and drags it, an event listener changes the width of the left element, then re positions the 3rd div accordingly.
However, I am getting a strange error where the left element in question seems to disappear / get removed after changing the width. I have verified this by doing a $("#divID").length to the console before and after. Before shows a count of 1, after shows a count of 0. This is causing an error in one of the functions that uses the $("#divID").offset() function.
Here is the associated code. The $("#"+resultsDiv) is the left side which I referred to previously.
/**
* This will create an invisible div between the results pane (left) and map (right) that will allow the user to click and resize
*/
function handleResize() {
let e = document.createElement('div');
setResizeProperties(e);
document.body.appendChild(e);
$(e).mousedown(function() {
$("#"+resultsDiv).mousemove(function(el) {
doResize(el,$(this));
});
}).mouseup(function() {
$("#"+resultsDiv).unbind("mousemove",doResize);
});
$(window).resize(function() {
setResizeProperties(e);
});
}
/**
* Actually change the length
* #param el to get mouse page X from
* #param e of the invisible resize handle object
*/
function doResize(el,e) {
console.log($("#"+resultsDiv).width());
$("#"+resultsDiv).css("width",(el.pageX - 10 - $("#"+resultsDiv).offset().left));
console.log($("#"+resultsDiv).width());
console.log();
setResizeProperties(e);
}
/**
* Set the resize properties for the div element
* #param e of the invisible resize handle obbject
*/
function setResizeProperties(e) {
$(e).attr("id","resizeHandler");
//$(e).css("visibility","hidden");
$(e).css("background-color","red");
$(e).css("width","20px");
$(e).css("height",$("#gMapContainer").css("height"));
$(e).css("cursor","ew-resize");
$(e).css("position","absolute");
console.log($("#"+resultsDiv).length);
$(e).css("left",$("#"+resultsDiv).width() + $("#"+resultsDiv).offset().left);
$(e).css("top",$("#resultsContainer").offset().top);
$(e).css("z-index",10000);
}
Here is a link to the JS Fiddle:
https://jsfiddle.net/BrandonQDixon/pt70yLbs/
If not already set, it uses the latest version of JQuery.
This is pretty much what I'm working on: https://jsfiddle.net/atg5m6ym/2625/
I'm animating a div with jQuery to move left, then logging to the console when I hover over the div and when I move my mouse away from it:
$("div").animate({left: '250px'}, 6000);
$('div').hover(function() {
console.log("Mouse hovered on div!");
}).mouseleave(function() {
console.log("Mouse left div!");
})
Naturally, the program will run console.log("Mouse hovered on div!"); once I put my mouse on the element.
However, if I leave my mouse idle and the animated element moves onto it, nothing in $('div').hover(function(){}) will run. I have to move my mouse onto the element for the code to run, not let the element come to the mouse.
The same thing also happens if I hover onto the element, and then leave my mouse idle. Nothing in $('div').mouseleave(function(){}) will run after the element leaves, until I move my mouse from its position.
Is there any way to work around this? I am working with animated divs and I need code to run even if the mouse is idle and the divs pass through it.
Manually take the mouse's last known position and compare it to the position of the circle. This is kind of extensive but it should get you the right results.
Here is a JSFiddle:
https://jsfiddle.net/3vpaoj59/
$("div").animate({left: '250px'}, 6000);
$(document).ready(function() {
// record down the position of the cursor
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
// boolean to know if hovered or not, and to know whether to report in console.log
var hover = false;
// function to call by setinterval to check if mouse is within radius
function checkMouse(){
// find the centerpoint of the circle by taking its position then adding half its width/height to each coordinate
var left = $("#foo").offset().left+$("#foo").width()/2;
var top = $("#foo").offset().top+$("#foo").height()/2;
// use pythagorean theorem to find distance between two points
var xdist = Math.pow(Math.abs(cursorX - left),2);
var ydist = Math.pow(Math.abs(cursorY - top),2);
var hypotenuse = Math.round(Math.sqrt(xdist+ydist));
// check if the distance is less than radius
if(hypotenuse <= $("#foo").width()/2 && !hover){
// if true and not already reported true, report then fix
console.log("mouse hovered on div!");
hover = true;
} else if (hypotenuse > $("#foo").width()/2 && hover){
// if false and not already reported false, report then fix
console.log("mouse left div!");
hover = false;
}
}
// repeatedly call this
setInterval(checkMouse, 100);
});
I changed the div's ID to "foo" for convenience. Make sure to do this as well so that the code works for your project, or modify the JS to not use "foo".
Explanation:
The reason why your problem was occurring was because your mouse's coords are only updated every time you move your cursor, and that's when hover states are checked by .hover. As such, we need to emulate the event that determines hover and call it repeatedly even when the cursor hasn't moved to make sure the hover state is updated.
I'm pretty new at Raphael JS, and SVG in general. Currently I'm using SVG and Raphael on a map-functionality.
I'm having an issue with a hover effect which offsets the given element you hover with 10px. However, if you move your mouse slowly into the element the hoverIn and hoverOut will happen a bunch of times resulting in flickering.
I think I could resolve this by cloning the countries and leave it hidden and stationary, when hovering. I could do this I say, because the map contains hundreds of shapes...
What is the approach? What should I do?
If I understand correctly the element moves when you hover over it, which cause the hoverOut event. What do you want to happen with slow mouse movements? It moves once, stays moved until the mouse gets inside?
You need to set a variable on the element to show when it's been shifted 10px. Then you can do something like (pseudocode)
hoverIn() {
if (isShifted) {
inWhenShifted = true
} else {
// offset element
isShifted = true
}
hoverOut() {
if (isShifted) {
if (inWhenShifted) {
// put element back
isShifted = false
inWhenShifted = false
} else {
// do nothing?, this is the case where the hoverOut fired
// because we moved the element
}
} else {
// do nothing?, this is the case where we hoverOut again after shifting
// the element back
}
}
I am trying to create an 'application' contained in a div on a web page. This can't be any larger than certain dimensions (lets say: 550px by 280px). I have a menu with at least 1-3 sub menus for each item. The problem is, while I know the submenu is no larger than 280px high, the submenus often extend beyond the parent div's bounds (except for the last one which always grows upward not down).
Is there any way to make the menus grow up or down depending on whether it will extend beyond the div's bounds?
Here is a JSFiddle: http://jsfiddle.net/3FqcG/
Notice how the "Salzburg" submenu grows down beyond the bounds of the black DIV? I want that to grow up if it is too long and down if there is enough room.
Currently, I am just using the basic initialization: $( "#menu" ).menu();
Thanks!
I don't believe you can do this in CSS.
This leaves us with javascript. The basic idea is to:
calculate the baseline of the menu
if this lies outside the boundary
move the menu upwards to correct the position
live almost happily ever after
But, we have one major issue:
Though we capture the focus of an element, we don't know when its submenu is displayed & positioned. So although your problem is technically solved, it is by far not a desirable solution.
UPDATE
The best workaround I could come up with was to:
Turn off the animation (to avoid ugly glitches)
Add a watcher that would constantly monitor the element that is about to be opened
If opened, apply the position correction
Anyway, if you consider coming this far, you might as well override the default positioning of the jquery ui component, with the note that you will not be able to easily update the library. Update: or try Rudy Garcia's version if it works
Demo
Code of the demo:
var BASE_OFFSET = $('#menuContainer').offset().top;
var MAX_OFFSET = $('#menuContainer').height(); // get the offset of the container
var whenVisible = function($el, callback){ //executes callback when $el is visible
if($el.is(':visible')){ // if visible
callback(); // execute callback
}else{ // otherwise
setTimeout(function(){whenVisible($el, callback);},10); // do the same check in 10 ms
}
};
var fixPosition = function($menu){ // correct the position of the menu in respect to #menuContainer
var h = $menu.outerHeight(true); // take the height of the menu
var menuBottom = $menu.offset().top + h - BASE_OFFSET; // the baseline of the menu (taking into consideration the BASE_OFFSET)
if(menuBottom > MAX_OFFSET){ // if this is outside the MAX height
var diff = MAX_OFFSET - menuBottom; // calculate the difference
var newTop = $menu.position().top + diff; // modify current positioning with the calculated diff value
$menu.css('top', newTop + 'px'); // apply it to top (which is also used by jquery to position submenus
}
$.fx.off = false; // switch animations back on
};
$( "#menu" ).menu().on('menufocus', function(ev, ui){ // on the event menufocus
var $ui = $(ui.item); //take the focused element
var $menu = $ui.children('ul'); // take its related submenu
if($menu.length === 0){ // if there is none
return; // just terminate
}
$.fx.off = true; // switch off jQuery effects (otherwise you'll have glitches)
whenVisible($menu, function(){fixPosition($menu);}); // execute fixPosition when $menu is visible
});
You could also look at the API for this widget:
http://api.jqueryui.com/menu/
You can use the position option to position the elements how you want.
This will change the position so that they are within the box, however you will want to dynamically access the last to give it the position you want as the code below will change all menu items to move up 50.
$( "#menu" ).menu({ position: { my: "left top", at: "right+5 top-50" } });
A complete list of positioning options are also found here: http://api.jqueryui.com/position/
Apparently jquery UI has accounted for this and has given the option "within" to make sure your element stays within another element of your choice.
Therefore Your solution should be this:
$( "#menu" ).menu({ position: {within: '#menuContainer' } });