Note: This was originally posted at SO, and as per the recommendation moving to this form.
In my effort to learn JS on the backdrop of SVG development, I got lot of help from SO so far. The answer to previous query was the best to understand closure; its usage and caveats in very short time. While continuing on the same line, I was trying to breakdown the below function so that it is more readable and easy to expand. It was part of an answer given by @Phrogz. I could not think a way to keep the onmove closure outside the loop.
If someone can help me with a pseudo code/skeleton of how can it be done without too many variable to retain the state (like button click state while moving etc), it would clarify many of my doubts regarding how the closure can be assigned etc. You may also break the function into 3 event handlers (mousedown, mousemove, mouseup). I could not think a way to do this while keeping the context (mousemove only triggers when the mouse is down, as it is within the closure).
I use jQuery typically in my projects, so if that helps to make the above code more maintainable, that would help too.
for (var a=svg.querySelectorAll('.drag'),i=0,len=a.length;i<len;++i){
(function(el){
var onmove; // make inner closure available for unregistration
el.addEventListener('mousedown',function(e){
el.parentNode.appendChild(el); // move to top
var x = el.tagName=='circle' ? 'cx' : 'x';
var y = el.tagName=='circle' ? 'cy' : 'y';
var mouseStart = cursorPoint(e);
var elementStart = { x:el[x].animVal.value, y:el[y].animVal.value };
onmove = function(e){
var current = cursorPoint(e);
pt.x = current.x - mouseStart.x;
pt.y = current.y - mouseStart.y;
console.log("pt.x:" + pt.x + "pt.y:" + pt.y);
var m = el.getTransformToElement(svg).inverse();
m.e = m.f = 0;
pt = pt.matrixTransform(m);
el.setAttribute(x,elementStart.x+pt.x);
el.setAttribute(y,elementStart.y+pt.y);
var dragEvent = document.createEvent("Event");
dragEvent.initEvent("dragged", true, true);
el.dispatchEvent(dragEvent);
};
document.body.addEventListener('mousemove',onmove,false);
},false);
document.body.addEventListener('mouseup',function(){
document.body.removeEventListener('mousemove',onmove,false);
},false);
})(a[i]);
}