Javascript Resizing

Hi all,

I'm trying to build a resize script so when a user hovers over the bottom line of a div they can click down and resize(like a window)

It is working however if the mouse moves too quickly the resize function stops running

There is no "mouseout" event only a mousedown and mouse up

for reference elementObj.newTop is set to the objects offsetTop (based on it's owners) once the user clicks down so that it isn't processed every time the mouse is moved - the code below is used while the mouse is down and the mouse is moved

Any ideas?
thanks for your help
elementResize : function(e)
		{
			
			var newMouseY = e.clientY-elementObj.newTop;
			elementObj.style.height = newMouseY + "px";
			elementObj.bottom = getTopPos(elementObj) + newMouseY;
			return false;
		}

Open in new window

LVL 3
cevomanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Pawel WitkowskiSenior Javascript DeveloperCommented:
To do any dragables you need 3 events.

mousedown - event on bottom line of div - function that will be fired on start draging window, it need to set variable that holds information what element is dragged,

mousemove - event on whole document - function that need to check if dragging is on (check is variable is set with proper element) and extends its size - it have to be on document level, otherwise if you move your mouse fast there will be diffrent event called for other elements instead of bar element,

mouseup - event also on document level - just to be sure that it will be cleared properly



any questions?
0
cevomanAuthor Commented:
The function is part of a bigger class which i have created
Mousedown does exist but as part of the bigger function so if mouse down happens anywhere but the bottom line it will move the box and not resize it.

The problem isn't that the resize isn't functioning (as above it works well) the problem is that if the mouse moves to quickly javascript doesn't resize any more until you mouse down on the bottom line again (ie it just switches off any current "onmousemove" event handler)

0
Pawel WitkowskiSenior Javascript DeveloperCommented:
Yes I know what is the problem and I gave you sollution for that... Problem is that events that you want to relay on are not fired because if you get your mouse outside of element - there is no longer event for it. So you need to listen on whole document...
0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

cevomanAuthor Commented:
Hi there,

with respect - where did you give me a solution for my problem?
all you have provided is 3 events which need to happen (which are happening) for an element to be draggable.

Once the 'element.onmousedown' has fired, the 'document.onmousemove' is set and fires when the mouse moves fired - under normal conditions this will only return to null if the mouse is up,
however I have removed that part of the class so even if the mouse is up the event 'onmousemove' still runs - which it does except if I move the mouse too quickly

Kind regards
James

0
Pawel WitkowskiSenior Javascript DeveloperCommented:
is that more clear ? You have to do this otherwise you lose event context for element.

 
 
var dragged;
element.onmousedown = function()
{
   dragged = this;
}
 
document.onmousemove = function()
{
 
if (dragged){
   // animate dragged
}
}
 
document.onmouseup = function()
{
dragged = null;
}

Open in new window

0
cevomanAuthor Commented:
Hi there,

as I have explained in each of the previous messages - these functions already exist and are already doing what they should be doing, I have briefly disabled 'document.onmouseup' so that the event handler for document.onmousemove is always running but the event still ends if the mouse is moved too quickly.

Kind regards
James
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
can you show me page with some example for this so I can look at this with mine tools ?
0
cevomanAuthor Commented:
Hi there,

I have attached the full code including a Div which is re-sizeable
you have to move the mouse very slowly for it to resize - I have also made it so the mouse can hover between the  bottom and -10 pixels to resize the bottom (makes it easier to locate the edge)

Kind regards
James
<script language=javascript>
	 function getTopPos(inputObj)
	{
	
		var returnValue = inputObj.offsetTop;
		while((inputObj = inputObj.offsetParent) != null){
			returnValue += inputObj.offsetTop;
		}
		return returnValue;
	}
 
 	var ElementRMove = 
	{
		elementObj : null,
		
		initResize : function(obj,e)
		{
			
			document.onmousemove = ElementRMove.elementCheckResize;
			obj.onmouseout = ElementRMove.checkResizeEnd;
			obj.bottom = getTopPos(obj) + obj.offsetHeight;
			elementObj = obj;
			return false;
			
		},
		
		elementCheckResize : function(e)
		{
			
			if(e.clientY > (elementObj.bottom-10) && e.clientY < elementObj.bottom)
			{
				document.body.style.cursor = "s-resize";
				elementObj.onmousedown = ElementRMove.initElementResize;
			}
			else{document.body.style.cursor = "default";}
			return false;
		
		},
		
		checkResizeEnd : function()
		{
			document.onmousemove = null;
			elementObj = null;
		},
		
		initElementResize : function (e)
		{
			
			document.onmousemove = ElementRMove.elementResize;
			document.onmouseup = ElementRMove.resizeEnd;
			elementObj.newTop = getTopPos(elementObj);
			return false;
			
		},
		
		elementResize : function(e)
		{
			var oldHeight = elementObj.offsetHeight;
			var newMouseY = e.clientY-elementObj.newTop;
			
			elementObj.style.height = newMouseY + "px";
			return false;
		},
		
		resizeEnd : function()
		{
			document.onmouseup = null;
			document.onmousemove = null;
			document.body.style.cursor = "default";
			elementObj = null;
			return false;
		}
	
	}
</script>
 
<div style="border: 1px solid #000000;" onmouseover="ElementRMove.initResize(this,event);">hello</div>

Open in new window

0
Pawel WitkowskiSenior Javascript DeveloperCommented:
Sorry to tell that.. dont get me wrong... but I never saw so strange solution. I tried to patch it somehow but there are so many errors and bad design concept that I will create for you from scratch - analyse it then please! I will  give it to you in 5 min.
0
cevomanAuthor Commented:
The code was just banged together to see how it could work for a specific site admin panel, i would have refined it later but that part of the code was driving me nuts it seems as if to much is being processed for the event handler to keep up with the mouse moving but I have no idea thats why i wanted a fresh pair of eyes
0
cevomanAuthor Commented:
just to mention, there shouldn't be any errors in this code unless you run it from IE (which it's not been designed to run from)
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
Generally based on your code, but changed almost everything. Notice that you need to initEngine first to use it - in initalisation we attach those events to document. Rest is just to analyse for you.
<script language=javascript>
         function getTopPos(inputObj)
        {
        
                var returnValue = inputObj.offsetTop;
                while((inputObj = inputObj.offsetParent) != null){
                        returnValue += inputObj.offsetTop;
                }
                return returnValue;
        }
 
        var ElementRMove = 
        {
                elementObj : null,
                initEngine : function()
				{
					document.onmousemove = ElementRMove.mouseMove;
					document.onmouseup = ElementRMove.mouseUp;				
				},
				mouseMove : function (e)
				{
				    if (ElementRMove.elementObj)
					{
						var newMouseY = e.clientY-getTopPos(ElementRMove.elementObj);                        
                        ElementRMove.elementObj.style.height = newMouseY + "px";
					}
				},
				mouseUp : function()
				{
					ElementRMove.elementObj=null;
				},
				mouseOut : function()
				{
				
					if (ElementRMove.elementObj===null)
					{
						document.body.style.cursor = "default";
					}
				
				},
                initResize : function(obj)
                {
					if (ElementRMove.elementObj === null)
					{
						document.body.style.cursor = "s-resize";
					}
					obj.onmousedown = function()
					{
						ElementRMove.startResize(obj);
					}
					obj.onmouseout = ElementRMove.mouseOut;
 
                },
				
                startResize: function(obj)
				{
					ElementRMove.elementObj = obj;			
				}      
        }
		ElementRMove.initEngine();
</script>
 
<div style="border: 1px solid #000000;" onmouseover="ElementRMove.initResize(this);">hello</div>

Open in new window

0
Pawel WitkowskiSenior Javascript DeveloperCommented:
ahh and sorry for naming functions - just change them to what you want ;)
0
cevomanAuthor Commented:
Hi there,

It works - which is great

But the reason my code was designed the way it was, was to allow there to be multiple objects on one screen (all resizeable) and also so the mouse is tracked when inside an object (so it knows when it is on the bottom line) as the design is to allow for an object to be resized by width and dragged finally to ensure the "class" doesn't hog the mousemove / mouseup events and allows other objects in a form to take focus for the same function or different

Adding the relevant code to yours brings it almost identically back to mine and causes the same issue.
Any suggestions?
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
???

There should be no issues with mine solution - it creates one global dragging element that can drag one item at any given time. If you mouseover on another element it should work... have you test it  already?
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
Try this i think that I know what you mean
<script language=javascript>
         function getTopPos(inputObj)
        {
        
                var returnValue = inputObj.offsetTop;
                while((inputObj = inputObj.offsetParent) != null){
                        returnValue += inputObj.offsetTop;
                }
                return returnValue;
        }
 
        var ElementRMove = 
        {
                elementObj : null,
                initEngine : function()
				{
					document.onmousemove = ElementRMove.mouseMove;
					document.onmouseup = ElementRMove.mouseUp;				
				},
				mouseMove : function (e)
				{
				    if (ElementRMove.elementObj)
					{
						var newMouseY = e.clientY-getTopPos(ElementRMove.elementObj);                        
                        ElementRMove.elementObj.style.height = newMouseY + "px";
					}
				},
				mouseUp : function()
				{
					if (ElementRMove.elementObj!==null)
					{
						ElementRMove.elementObj=null;
						ElementRMove.elementObj.onmousedown = null;
						ElementRMove.elementObj.onmouseout = null;
					}
				},
				mouseOut : function()
				{
				
					if (ElementRMove.elementObj===null)
					{
						document.body.style.cursor = "default";
					}
				
				},
                initResize : function(obj)
                {
					if (ElementRMove.elementObj === null)
					{
						document.body.style.cursor = "s-resize";
						obj.onmousedown = function()
						{
							ElementRMove.startResize(obj);
						}
						obj.onmouseout = ElementRMove.mouseOut;						
					}
 
 
                },
				
                startResize: function(obj)
				{
					ElementRMove.elementObj = obj;			
				}      
        }
		ElementRMove.initEngine();
</script>
 
<div style="border: 1px solid #000000;" onmouseover="ElementRMove.initResize(this);">hello</div>
<div style="border: 1px solid #000000;" onmouseover="ElementRMove.initResize(this);">world</div>

Open in new window

0
cevomanAuthor Commented:
Hi there,

It definitely works but it is dependant on only those objects can utilize onmousemove and onmouseup so if there is another class / object on a page which takes control of onmousemove or onmouseup the script needs to be reinitialized.

Kind regards
James
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
google ->  addEventListener  MDC   ;)
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
what I basicaly create is just an example - if you worried about what you saying just use addEventListener instead of simply .onmouseover
0
Pawel WitkowskiSenior Javascript DeveloperCommented:

function registerEvent(el,eventName, func)
{
 
if (el.addEventListener){
  el.addEventListener(eventName, func, false); 
} else if (el.attachEvent){
  el.attachEvent('on'+eventName, func);
}
 
}
 
 
registerEvent(document,"mousemove",function(){ console.log('a')});

Open in new window

0
Michel PlungjanIT ExpertCommented:
I believe console does not work out of the box...
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
I believe that autor understand idea of how it should work like
0
Michel PlungjanIT ExpertCommented:
Only if he has firebug installed
0
Pawel WitkowskiSenior Javascript DeveloperCommented:
Code I provide is just an example - it will not work with anything else if is not well understanded / correctly called
0
GoofyDawgCommented:
As opposed to sizing the div directly, what you might think about doing is creating a small drag bar that sits right below the div you want to resize. I haven't tested your code, but it looks like you have the elements you need to make it work. The point is that dragging the bar, then resizing the div is a lot more efficient then resizing the div which, especially in IE, makes the browser continuously re-render the div and its contents. By just dragging the bar, then responding to the "drop," you can then simply set the div's height.

A lot of browser-based content panels use this type of panel sizing technique.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Pawel WitkowskiSenior Javascript DeveloperCommented:
Maybe not perfect but please try this one.
<script language=javascript>
 
		function registerEvent(el,eventName, func)
		{
			if (el.addEventListener){
			  el.addEventListener(eventName, func, false); 
			} else if (el.attachEvent){
			  el.attachEvent('on'+eventName, func);
			}
		}
		function removeEvent(el,eventName, func)
		{
			if (el.addEventListener){
			  el.removeEventListener(eventName, func,false); 
			} else if (el.detachEvent){
			  el.detachEvent('on'+eventName, func);
			}
		}		
 
         function getTopPos(inputObj)
        {
        
                var returnValue = inputObj.offsetTop;
                while((inputObj = inputObj.offsetParent) != null){
                        returnValue += inputObj.offsetTop;
                }
                return returnValue;
        }
         function getLeftPos(inputObj)
        {
        
                var returnValue = inputObj.offsetLeft;
                while((inputObj = inputObj.offsetParent) != null){
                        returnValue += inputObj.offsetLeft;
                }
                return returnValue;
        }
 		
 
        var ElementRMove = 
        {
                elementObj : null,
				dragY: false,
				dragX: false,
				draggingX: false,
				draggingY: false,
                initEngine : function()
				{
					registerEvent(document,"mousemove",ElementRMove.mouseMove);
					registerEvent(document,"mouseup",ElementRMove.mouseUp);
				},
				mouseMove : function (e)
				{
				    if (ElementRMove.elementObj)
					{
						if (ElementRMove.draggingY)
						{
							var newMouseY = e.clientY-getTopPos(ElementRMove.elementObj);                        
							ElementRMove.elementObj.style.height = newMouseY + "px";
						}
						if (ElementRMove.draggingX)
						{
							var newMouseX = e.clientX-getLeftPos(ElementRMove.elementObj);                        
							ElementRMove.elementObj.style.width = newMouseX + "px";
						}
					}
				},
				mouseUp : function()
				{
					if (ElementRMove.elementObj!==null)
					{
						removeEvent(ElementRMove.elementObj,"mousedown",ElementRMove._startResizeFunc);
						removeEvent(ElementRMove.elementObj,"mouseout",ElementRMove.mouseOut);
						ElementRMove.elementObj=null;
						ElementRMove.draggingX=false;
						ElementRMove.draggingY=false;
					}
				},
				mouseOut : function()
				{
				
					if (ElementRMove.elementObj===null)
					{
						document.body.style.cursor = "default";
					}
				
				},
                initResize : function(obj)
                {
					if (ElementRMove.elementObj === null)
					{
						ElementRMove._startResizeFunc=function()
						{
							ElementRMove.startResize(obj);
						};
						registerEvent(obj,"mousedown",ElementRMove._startResizeFunc);
						registerEvent(obj,"mouseout",ElementRMove.mouseOut);
						registerEvent(obj,"mousemove",ElementRMove.checkResize);
					}
                },
				
				checkResize: function(e)
				{
					if(e.clientY > (getTopPos(e.currentTarget)-10+e.currentTarget.offsetHeight) && e.clientY < getTopPos(e.currentTarget)+e.currentTarget.offsetHeight)
					{
						ElementRMove.dragY=true;
					}else
					{
						ElementRMove.dragY=false;
					}
					
					if(e.clientX > (getLeftPos(e.currentTarget)-10+e.currentTarget.offsetWidth) && e.clientX < getLeftPos(e.currentTarget)+e.currentTarget.offsetWidth)
					{
						ElementRMove.dragX=true;
					}else
					{
						ElementRMove.dragX=false;
					}
					
					if (ElementRMove.dragY)
					{
						document.body.style.cursor = "s-resize";
					}
					else if (ElementRMove.dragX)
					{
						document.body.style.cursor = "w-resize";
					}
					else
					{
						document.body.style.cursor = "default";
					}
				},
				
                startResize: function(obj)
				{
					if (ElementRMove.dragY)
					{
						ElementRMove.elementObj = obj;
						ElementRMove.draggingY=true;
					}
					if (ElementRMove.dragX)
					{
						ElementRMove.elementObj = obj;			
						ElementRMove.draggingX=true;
					}					
				}      
        }
		ElementRMove.initEngine();
</script>
 
<div style="border: 1px solid #000000;width:150px" onmouseover="ElementRMove.initResize(this);">hello</div>
<div style="border: 1px solid #000000;" onmouseover="ElementRMove.initResize(this);">world</div>

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.