Jump to content

Recommended Posts

So I have a drag and drop script I've modified and I want to add some functionality to it.  When the drag stops and the mousebutton is lifted, I want the current span to copy the background color of the span that was being dragged.  (You can see http://www.unitorganizer.com/websitebuilder/testing/coloradder.html for an example of what I mean by this)  In other words, the user can drag colors over from a colorbar and change the color of a box on the screen.

I've managed to make it work when there is exactly one box, but now I want to add multiple boxes which means that the script has to check to see which box it is over.  If there is an easy way to do this, let me know.  What I'm trying to do is check each span, get its location and dimensions, and given the location of the mouse, use these to determine which element I'm over.  But...its...not...working...

Checking function code below:

Also this drag and drop the color thing doesn't actually work at all in Firefox, and I'm not sure why.  Thanks for your help.

[code]
function getSpan (x,y){
  var allSpan = document.getElementsByTagName('span');
  for (i=0;i<allSpan.length;i++){;
  alert(allSpan[i].id);
alert(parseInt(allSpan[i].style.top));
      var spanTop = allSpan[i].style.top;
      var spanLeft = allSpan[i].style.left;
      var spanWidth = allSpan[i].style.width;
      var spanHeight = allSpan[i].style.height;
      var minleft = (x > spanLeft);
      var maxleft = (x < (spanLeft + spanWidth));
      var mintop = (y > spanTop);
      var maxtop = (y < (spanTop + spanHeight));
      if (minleft && maxleft){
        if (mintop && maxtop) {
          spanId = allSpan[i].id;
          return spanId;
        }
      }
    }
spanId = "box1";
  return spanId;
}
[/code]

All of the code from this drag and drop js file.

[code]
var ie=document.all;
var nn6=document.getElementById&&!document.all;

var isdrag=false;
var x,y;
var dobj=null;

function whichElement(e)
{
var targ
if (!e) var e = window.event
if (e.target) targ = e.target
else if (e.srcElement) targ = e.srcElement
if (targ.nodeType == 3) // defeat Safari bug
  targ = targ.parentNode
var tname
tname=targ.id
return tname;
}

function movemouse(e)
{
  if (isdrag)
  {
    dobj.style.left = nn6 ? tx + e.clientX - x : tx + event.clientX - x;
    dobj.style.top  = nn6 ? ty + e.clientY - y : ty + event.clientY - y;
    return false;
  }
}

function selectmouse(e)
{
  var fobj      = nn6 ? e.target : event.srcElement;
  var topelement = nn6 ? "HTML" : "BODY";

  while (fobj.tagName != topelement && fobj.className != "dragme")
  {
    fobj = nn6 ? fobj.parentNode : fobj.parentElement;
  }

  if (fobj.className=="dragme")
  {
    isdrag = true;
    dobj = fobj;
    tx = parseInt(dobj.style.left+0);
    ty = parseInt(dobj.style.top+0);
    x = nn6 ? e.clientX : event.clientX;
    y = nn6 ? e.clientY : event.clientY;
    document.onmousemove=movemouse;
    return false;
  }
}

function stopDrag() {
  isdrag=false;
if (!(typeof dobj=="null")) {
  x = dobj.style.left;
x = parseInt(x);
}
if (!(typeof dobj=="null")) {
y = dobj.style.top;
y = parseInt(y);
}
spanId = getSpan(x,y);
if (spanId=="none"){ return; }
  var divName = whichElement(event);
var divId = document.getElementById(divName);
var divStyle = divId.style.backgroundColor;
var divBox = document.getElementById(spanId);
divBox.style.backgroundColor = divStyle;
}

function getSpan (x,y){
  var allSpan = document.getElementsByTagName('span');
  for (i=0;i<allSpan.length;i++){;
  alert(allSpan[i].id);
alert(parseInt(allSpan[i].style.top));
      var spanTop = allSpan[i].style.top;
      var spanLeft = allSpan[i].style.left;
      var spanWidth = allSpan[i].style.width;
      var spanHeight = allSpan[i].style.height;
      var minleft = (x > spanLeft);
      var maxleft = (x < (spanLeft + spanWidth));
      var mintop = (y > spanTop);
      var maxtop = (y < (spanTop + spanHeight));
      if (minleft && maxleft){
        if (mintop && maxtop) {
          spanId = allSpan[i].id;
          return spanId;
        }
      }
    }
spanId = "box1";
  return spanId;
}
document.onmousedown=selectmouse;
document.onmouseup=stopDrag;
[/code]
Since this is based on JS, I'd recomment creating the spans using JS as well, this way you'll have full control over position, etc..

You'll need to create an array foreach span to hold the span top left corner x and y, the width and the height in an array (IE and Firefox will add the padding to the width, while Opera won't)

When you let the mouse go, you can go through that array (not all the spans because you may use other spans for something else) and check if the x and y position withen which span

Here is a sample code, just to show how to get the element position
[code]
<script language="javascript">
var spans = new Array();

var is_Opera = (window.navigator.userAgent.search("Opera") != -1);
var is_IE = ((window.navigator.userAgent.search("MSIE") != -1) && !is_Opera);

function createSpans(){
var widths = new Array(100,100,50,125);
var heights = new Array(50,100,50,150);
var bgs = new Array("#ffffcc","#cceecc","#33ffcc","#000000");
var x = new Array(25,150,250,400);
var y = new Array(10,125,300,500);

var sp = "";

for(i=0; i<widths.length; i++){
sp = document.createElement("SPAN");
sp.className = "floating";
sp.style.backgroundColor = bgs[i];
sp.style.width = widths[i]+"px";
sp.style.height = heights[i]+"px";
sp.style.top = y[i]+"px";
sp.style.left = x[i]+"px";

sp.id = "clr_"+i;

document.body.appendChild(sp);

spans.push(new Array(sp.id,widths[i],heights[i],y[i],x[i],bgs[i]));
}
}

function w_span(evt){
var right_x = 0;
var right_y = 0;
var id= "";

if(is_IE) evt=event;

for(i=0; i<spans.length; i++){
right_x = spans[i][1]+spans[i][4];
right_y = spans[i][2]+spans[i][3];

if ((evt.clientX >= spans[i][4]) && (evt.clientX <= right_x) && (evt.clientY >= spans[i][3]) && (evt.clientY <= right_y)){
id = spans[i][0];
}
}

if (id != ""){
alert(id+ " "+document.getElementById(id).style.backgroundColor);
}
}
</script>
<style>
.floating {display:block;
position:absolute;
border:solid #000000 1px;}
</style>
</head>

<body onload="createSpans();" onclick="w_span(event);">

</body>
</html>
[/code]

P.S. If you download the NoGray JS Lib there are a lot of functions you can use (such as the drag and drop lib)
The problem with using an array to create the new spans is that I want the user to be able to dynamically create these spans, then place them where they want on the page, and change their color afterward.  A bit like adding sticky-notes to a page, and being able to change the color, position, and size of the sticky notes. 

I've got the sticky-note code almost working, so people can create sticky notes, resize them and position them anyway they like, and I intend to add this color selector code to the project as well when I get it working.  Interestingly enough, it works on Safari, (and makes IE Mac crash something horrible).  I'll have to test Netscape and Opera next.

Dave
If you don't want to use the array, what you can do is set a onmouseup event on the document body, get the x and y and loop through the spans (with either a specific class so they are not mixed with other spans- or another way to identify them) and check if the x an y in that span.

The problems you may have if there are more then one span that overlap each other and the x and y position is on both.

to check if the x and y on any span, you can check if the x is bigger then the style left position and smaller then the top position plus the width, same thing with y.

Good luck
So I set this up, and it was pretty much what I was planning on doing, and it seems to work fine.  And it has exactly the problems you talked about.  When it checks for divs and two divs satisfy the criterion, I've currently got it set up so the last div is the one that is filled with the color, which is not precisely the behavior I want.  What I actually want is the div that is 'on top' to be filled.  Is there a way to reference the 'on-top' div?  It's not exactly z-index, since these two elements may have the same z-index, but it appears that whichever element shows up last in the DOm sits on the top if the z-indices are the same.  Therefore I see I'm going to need to encode a z-index breaker that checks to see if other divs are visually underneath the current selected div, and changes the selected div to the proper z-index to force it on top.  Unfortunately this does not seem like a simple task to me, and I might just not worry about this bug in my program for a while.

Dave
I think you may be able to do it in another way, you can set a global variable in the JS to hold the current div id and set onmouseover event on each div to set that variable for the div and onmouseout to clear that variable

Then when the mouse button is up, you can check which div filled that variable last.
If anyone can find the bugs in my code I'd sure love the help.  I've been working on it all day with no success.  Basically absolute every single time you grab a color box and drag it over one of the other boxes, you should change the color of the large box to the color of the colored box.  However it doesn't work every single time, in fact I can't figure out when it works exactly and when it doesn't.  I have noticed that it seems to work less often (but frustratingly occasionally works) when you drop the colors on top of the words, or the arrow in the corner.  I even tried removing these divs but to no avail, the code still occasionally makes mistakes.

If you could help with this, I would greatly appreciated it.

Check out http://www.unitorganizer.com/download/coloradder.html

Also rather than put all the code below I've created an archive of the site which you can download here:

http://www.unitorganizer.com/download/color.zip

Dave

The problem could be because when you drag the color over the div, the div never gets the onmouseover event (because the mouse still over the color swatch), and the code will run before the onmouseover event is triggered. you can try to set a short time out (maybe 10 or 50) before the color change and see if thats work.
I've been doing some testing, and I think the problem is actually different.  When I separate the boxes underneath from each other, I never have any problems.  However when I move my mouse over one of the other boxes first, before moving it into the destination box, I have difficulties.  Apparently the mouseover event itself takes some time to fire (even though it's extremely minimal code).  I wonder if it's actually a problem with my mouse itself. 

Oh I noticed something.  When there are multiple Mouseover events, it returns the first one in the DOM when what I want it to do is return the last one (because that one will be on top).

I'd love to see if someone else has managed to get something like this working (in Javascript) so I could examine their code.

My wife suggested that instead of using floating colors (which are cool) you could double click the destination box, and then click to choose the color.  I think that has its own set of problems however.

Thanks for all of your help.  I'm going to keep working at this and see if I can find a solution.  Wish I knew Javascript better.

Dave
I think I'm going to go back to my original version of this, and work on getting the z-indexing part to work properly.  Basically what I'll do is create an array of the z-indexes of the spans below, and whichever of the spans qualifies by area, I'll use the spab with the highest z-index.  Then I'll create a button to allow the user to choose the z-index of the box.  It will probably be easier than trying to find the error with the mouseover here.  Besides I already know my original code always worked, it just occassionally colored the wrong box.

Dave
Code ----Fixed---- See it at:

http://www.unitorganizer.com/stickies

Dave

EDIT:  Lordy what a doozy!  I found an extra comma at the very bottom of the variable declaration in domdrag.js which Firefox apparently ignores, and IE is confused by.  Now I can start debugging the errors IE is generating for my zIndex fix (fixed).

EDIT2:  Also managed to add a re-sizeable option and a fit-to-element textarea both of which were surprisingly easy to do.
 
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.