views:

155

answers:

5

I was wondering if it is possible to set background-color with help of mouse coordinates.

What i have is:

I have a DIV-A which is draggable and some other divs which are droppable.

What i need is :

I need to highlight other divs on my page which are droppable, whenever my DIV-A passes over them. What i have is mouse coordinates, is it possible to apply css on the bases of mouse coordinates using jquery.

A: 

You can use .hover() for this, so when the mouse is over the div, change it's background colour:

$("yourdiv").hover(function () {
    $(this).css("background-color", "#ff0000");
  },
  function () {
    $(this).css("background-color", "#ffffff");
});
Tim
since the downvoter didn't add a comment I will: This will not work because "yourdiv" will not be "hovered" because it is being blocked by the draggable.
David Murdoch
A: 

Declare selector and selector2 to whatever you want...

$(selector).mousemove(function(event) {

   // Set some bounds, these are arbitrary here not sure what sort of area your looking for...
   var lowerXBound= 0,
       upperXBound = 100,
       lowerYBound = 0,
       upperYBound = 100,
       currentX = event.pageX,
       currentY = event.pageY;

   var color = currentX > lowerXBound && currentX < upperXBound && currentY > lowerYBound && currentY < upperYBound ? 'red' : 'green';

   $(selector2).css('background-color', color);
});
gmcalab
ah, you beat me to it...ish. We are both on the same track...but I think my answer may cover the multiple droppables better. What do you think?
David Murdoch
but i dnt have ids for droppable divs, as they are created dynamically
Ashish Rajan
@David Murdoch, I like your solution too, nice one man.
gmcalab
@Ashish Rajan - instead of an ID use a class for the droppable. then the selector would be the class instead of an ID for my solution as well.
gmcalab
+2  A: 

Something like the following may work. You will probably need to deal with window's scrollLeft and scrollTop to get it perfect. You will probably want to throttle and memoize (if the drop positions don't change) it too.

Also, some more performance can be tweaked out of it by caching offset(), only binding mousemove when needed, and by tweaking the each loop to utilize an optimized loop (e.g. for(var i=droppables.length;i>-1;){var self = droppables.eq(--i);...}).

Also note that this will only change the color of the divs when the MOUSE passes over them...not necessarily when the draggable passes over them...this makes things a little more complicate but the function below should send you in the right direction.

$(document).mousemove(function(e){
     // this should be throttled...
     var x = e.pageX,
         y = e.pageY;
     // this loop could be optimized...
     $("div.droppables").each(function(){
         // these vars could be memoized...
         var self = $(this),
             divL = self.offset().left,
             divT = self.offset().top,
             divR = self.width() + divL,
             divB = self.height() + divT;
         // if the MOUSE coords are between the droppable's coords
         // change the background color
         if(x >= divL && x <= divR && y >= divT && y <= divB){
              self.css("background", "red");
         }
         else{
              // reset the background color
              self.css("background", "");   
         }
     });
});
David Murdoch
i have to ask...why the downvote? Please, do tell:
David Murdoch
@David Murdoch: getting error `missing variable name`
Ashish Rajan
I just tested it. no errors. I've updated the code a bit; try that. Also, post the code you are ACTUALLY using.
David Murdoch
its working but not the way i wanted it. I wanted to highlight the droppables whenever my draggable div passes over them
Ashish Rajan
@Ashish: Don't take this the wrong way...I'm not going to do all of the work for you...neither should any S.O. member. I have given you are GREAT starting point so that you can figure out the draggable's bounds and coordinates.
David Murdoch
yeah i realize that.. but problem is that currently the mouse event is associated with whole document and when a try it to anchor with my draggable div it doesn't work. Currently when my mouse passes over the div its highlighted, i want same when the draggable div passes over it.. anyways i will give it a try... Thanks....
Ashish Rajan
yay! another down-vote and no reason given. I'd really like to know why the answer should be voted down... :-(
David Murdoch
+1  A: 

Have a look at the "Visual feedback" sample over at jQuery UI, and as gmcalab mentioned, not having IDs is not an issue if you just use a class as the selector. Sorry if I'm not reading this correctly.

Lance May
nice, I didn't know about that!
David Murdoch
+2  A: 

I posted a demo for you here. Basically this cycles through each droppable position, so if you have a lot of them, it could really slow down mouse movement.

Oh, and I added two variables you can adjust if you want to increase the proximity to the droppable. Adjust the xmargin and ymargin variables as desired.

CSS

.draggable { width: 90px; height: 90px; padding: 0.5em; position: relative; top: 0; left: 0; z-index: 2; }
.droppable { width: 120px; height: 120px; padding: 0.5em; position: absolute; z-index: 1; }
#drop1 { top: 150px; left: 300px; }
#drop2 { top: 400px; left: 100px; }

HTML

<div class="draggable ui-widget-content">
  <p>Drag me to my target</p>
</div>

<div id="drop1" class="droppable ui-widget-header">
  <p>Drop here</p>
</div>

<div id="drop2" class="droppable ui-widget-header">
  <p>Drop here</p>
</div>

Script

$(function(){
 var xmargin = 10,
  ymargin = 10,
  drag = $('.draggable'),
  drop = $('.droppable'),
  dgw = drag.outerWidth() + xmargin,
  dgh = drag.outerHeight() + ymargin,
  pos = [];

 drop
  .droppable({
   //hoverClass: 'ui-state-active',
   drop: function(event, ui) {
    $(this).addClass('ui-state-highlight').find('p').html('Dropped!');
   }
  })
  // set up droppable coordinates array (left, top, right, bottom) for each element
  .each(function(i){
    var dropzone = drop.eq(i);
    var l = dropzone.position().left,
     t = dropzone.position().top,
     r = l + dropzone.outerWidth() + xmargin,
     b = t + dropzone.outerHeight() + ymargin;
   pos.push([l,t,r,b]);
  });

 drag
  .draggable()
  // bind to drag event, or this could be placed inside the draggable function
  .bind( "drag", function(event,ui){
   var l = ui.offset.left,
       t = ui.offset.top;
   // cycle through each droppable and compare current postion to droppable array
   drop.each(function(i){
    if ( ( l + dgw ) > pos[i][0] && l < pos[i][2] && ( t + dgh ) > pos[i][1] && t < pos[i][3] ) {
     $(this).addClass('ui-state-active');
    } else {
     $(this).removeClass('ui-state-active');
    }
   });
  });

});
fudgey
+1. this is almost exactly the implementation I was suggesting in my answer...just need to add some throttling. Also, changing the class of an element may be slower (depending on the number of elements and complexities of the selectors) than just applying the styles directly via javascript. p.s.: You know you can do `drop.eq(i)` right? It may be significantly faster if there are many drop targets.
David Murdoch
@David: Yeah I forgot about `.eq(i)`. I tested it and it is slightly faster when I tested it with 10 drop targets, thanks! Oh, and it looks cleaner too :)
fudgey
Use `$(this)` (and cache it) instead of `drop.eq(i)` where possible too. I doubt there will be any noticeable speed up unless you have like 1000 dropables...but its the clean way of doing things and encourages those new to jQuery to properly cache their dom lookups.
David Murdoch
Oddly enough, I started out using `$(this)` instead of the `drop.eq(i)` and it applied the class to all the drop boxes, so I left it, it must have been the initial code formatting...changing it back now. But I don't see a reason to cache it.
fudgey