Reputation: 6653
Alright, What i'm trying to achieve is an SVG
with inside it an foreighObjects
that can move.
I've made it possible to move ( draggable ), and the collission calculation looks alright to. There's only 1 problem. When i'm moving the object, it just spacing. It just runs out of the screen.
Here's some HTML
<div id="canvas">
<svg id="bewaar_holder" xmlns="http://www.w3.org/2000/svg" width="800" height="500" ></svg>
</div>
And here's the JS:
var kist_width = 60;
var kist_width_real = 62; // Dat is met alle margin's en borders erbij op
var kist_height = 60;
var kist_height_real = 62; // Dat is met alle margin's en border erbij op
var row_counter = 1;
function makeNew(){
var direction = $('input[name=direction]:checked').val();
var name = $("#input_row_name").val();
var length = $("#input_row_length").val();
var height = $("#input_row_high").val();
switch(direction){
case 'lr':
var leHTML = '<foreignObject id="foreign_row_' + row_counter + '" class="node obstacle foreign_drag" x="' + (10) + '" y="' + (10 ) + '" width="' + (( kist_width_real * length ) + kist_width_real ) + '" height="' + (kist_height + 2) + '"><body xmlns="http://www.w3.org/1999/xhtml">';
leHTML += '<div class="row_holder_lr draggable_row" id="row_' + row_counter + '" ><div class="name_holder" >' + name + '</div>';
leHTML += makeLR(length, height);
break;
default:
alert("Er is een fout opgetreden waardoor de actie niet kon worden voltooid.");
break;
}
leHTML += '</div></body></foreignObject>';
document.getElementById('bewaar_holder').appendChild(parseSVG(leHTML));
makeDraggable(row_counter);
row_counter++;
}
function makeLR(length, height){
var add = "";
var counter = 1;
while(counter <= length){
add += '<div class="kist">';
add += '<sup>' + counter + '</sup>';
add += '<span>' + height + '</span>';
add += '</div>';
counter++;
}
return add;
}
/*
*
* Alle drag acties:
*
*/
$('body').on('drag', '.draggable_row', function() {
var elem_row = this;
var id = $(elem_row).attr('id');
id = id.replace("row_", "");
log("dragging row " + id);
var move_left = $(elem_row).css('left').replace(/[^-\d\.]/g, '');
var move_top = $(elem_row).css('top').replace(/[^-\d\.]/g, '');
if(parseInt(move_left) > 0 || parseInt(move_top) > 0){
var elem_foreign = $("#foreign_row_" + id);
var x1_cur = parseInt($(elem_foreign).attr('x')) + parseInt(move_left);
var x2_cur = (x1_cur + (parseInt($(elem_foreign).attr("width"))));
var y1_cur = parseInt($(elem_foreign).attr('y')) + parseInt(move_top);
var y2_cur = (y1_cur + (parseInt($(elem_foreign).attr("height"))));
$(elem_row).css('left', "0");
$(elem_row).css('top', "0");
if(!mayMove(id, x1_cur, x2_cur, y1_cur, y2_cur)){
log("may not move object...");
return false;
}
$(elem_foreign).attr('x', x1_cur);
$(elem_foreign).attr('y', y1_cur);
log("we just moved");
// return false;
}
});
function mayMove(id_cur, x1_cur, x2_cur, y1_cur, y2_cur){
var returnVal = true;
$('.obstacle').each(function(i, obj) { // Loop trough all objects
if($(obj).attr("id") != "foreign_row_" + id_cur){ // Ignore the dragging ( own ) object
var x1_obj = parseInt($(obj).attr('x'));
var x2_obj = (x1_obj + (parseInt($(obj).attr("width"))));
var y1_obj = parseInt($(obj).attr('y'));
var y2_obj = (y1_obj + (parseInt($(obj).attr("height"))));
var minX1 = Math.min(x1_obj, x1_cur);
var maxX1 = Math.max(x1_obj, x1_cur);
var minX2 = Math.min(x2_obj, x2_cur);
var maxX2 = Math.max(x2_obj, x2_cur);
if( maxX2 <= minX1 || minX2 >= maxX1 ){
log("overlapping with row_" + id_cur);
returnVal = false;
}
}
});
return returnVal;
}
function makeDraggable(id){
$("#row_" + id).draggable({
// grid: [ 40, 40 ]
});
}
function parseSVG(s) {
var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
var frag= document.createDocumentFragment();
while (div.firstChild.firstChild)
frag.appendChild(div.firstChild.firstChild);
return frag;
}
Here's an zip file with all the needed files. I tried to make an JSFiddle of it, but somehow that didn't work.
So basicly what's happening is that an user clicks on an button and that the function makeNew
is called. That makes an new svg element and put's it inside the svg. Then there's an draggable
call on the div ( it didn't work on the svg ).
Every time the div is being dragged, we could use the margin to add it to the foreignObject x and y coordinates
and empty the left and top of the div again.
Problem is that how more you move, the faster it will run away ( i doesn't stick with the mouse ).
So can anybody see the bug in this piece of code? I've been banging my head to the walls for hours...
EDIT 1
After a lot of more debugging i came to the realization that the $('body').on('drag'
is executed on every movement ( witch is good ). And the coordinates of the foreignObject
are updated "correct". It's just that the css of the elements ( the left and top values
) aren't updated. When i manually execute the command ($(elem_row).css('left', "0px");
) the values are updated. So that is the problem.
So it looks like some kind of async
"bug" ( not an real bug, but the setup of this piece of code make's it looks like it's an bug ) that the CSS isn't updated properly.
Only problem now... I don't know how to fix that. Do you guys got any thoughts?
EDIT 2
I've placed the code on an hosting of my, so you guys can see it without needing to download everything. The website
Upvotes: 0
Views: 172
Reputation: 3397
So after reviewing what you had, I went about making quite a bit of changes.
I have noted the changes with a CHANGE:
comment in the respective panes of this jsfiddle.
The biggest issues stem from the fact you are making objects draggable via jquery and then also performing some of your own calculations on top of that. This is causing some adverse effects with the widget.
I removed that bit of code and took advantage of jQuery's droppable
widget. With this you can tell the obstacles
to trigger the drop
event if anything touches it, causing it to revert back to its' original position.
This largely ignores the foreignObject
elements you create and focuses on the actually html element the browser normally works with.
Upvotes: 1