Friday, November 8, 2013

Combining Selectables And Draggables Using jQuery UI

we can call:
console.log(variable);
When we open up the page and open Firebug, it will print out what the variable contains, it is a great tool for debugging, keep it handy.
Now that we have the understanding on how it works with different classes, lets start looking at the code that makes it work. I have commented it to make it easier for you to translate on your own time.
The first bits of the code
// creates the selected variable
// we are going to be storing the selected objects in here
var selected = $([]), offset = {top:0, left:0};
console.log("This is the value of selected when it is created " +selected + "");
As you can see from above, our first line creates the variable selected and is able to store numerous values because we are setting up an array for this variable. And the offset, resets the top and left values. If you use console.log it will output: Object length=0 prevObject=Object jquery=1.2.6 notice the length is 0 that is fine we haven’t selected any items yet.
// initiate the selectable id to be recognized by UI
$("#selectable1").selectable();
This part above, calls the selectable to generate the selectable region. NOTE: that #selectable is container and is the box not each element we are selecting.
The following part is important because, this is the where we start to hook up selectables with the draggables.
// declare draggable UI and what we are going to be doing on start
$("#selectable1 div").draggable({
     start: function(ev, ui) {
          $(this).is(".ui-selected") || $(".ui-selected").removeClass("ui-selected");
	  console.log("The value of 'this' currently is: "+this);
          selected = $(".ui-selected").each(function() {
               var el = $(this);
	       el.data("offset", el.offset());
	       $(this).text("Selected and dragging object(s)");
	  });
console.log(selected);
offset = $(this).offset();
},
The part below, tells the draggable UI to create every element within to have dragging.
$("#selectable1 div").draggable({
$(this).is(".ui-selected") || $(".ui-selected").removeClass("ui-selected");
console.log("The value of 'this' currently is: "+this);
This next section above resets the select and drag, by removing the ui-selected class, when we output using console.log, to see the value of this is The value of ‘this’ currently is: [object HTMLDivElement].
selected = $(".ui-selected").each(function() {
     var el = $(this);
     console.log("The value of el is: "+el);
     el.data("offset", el.offset());
     $(this).text("Selected and dragging object(s)");
});
Now we are finally working with the selected variable we created at the start of this, we are to run through each element with the class of ui-selected. We are going to be storing the value of $(this) in the variable el, to make it easier to call and to work with the offset(); property later on.
el.data("offset", el.offset());
$(this).text("Selected and dragging object(s)");
We are going back to out el variable and working with the data object and the offset object. The offset object returns two integer values: top and right. The definition of the offset(); from the jQuery documentation is: Get the current offset of the first matched element relative to the view port.
The other line, changes the text of the elements to let us know that we have selected and are now dragging the objects stored in the variable selected.
Now that we have called offset we want to store it in the variable offset, for each DOM elements selected. The code that follows this part is below:
console.log("The new value of selected is now "+selected);
offset = $(this).offset();
console.log("The value of top value is "+offset.top+" and the left value is "+offset.left);
We have another console.log() to print out the selected value and it is storing the DOM element. Next we create the variable offset and store the offset() of the elements, I have printed the top and left values using console.log() above, the output is similar to: The value of top value is 207 and the left value is 672.
The next section below is the section of code that handles what is going to go on while we are dragging our selected elements. This part is also very important because we are bringing back the values of offset with the current values of the draggable ui, it stores the ui properties in ui.position.top and ui.position.left. Further down the code we will use the offset values to update the CSS top and left properties of the selected elements.
drag: function(ev, ui) {
     var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left;
     console.log("The value of dt is "+dt);
     selected.not(this).each(function() {
          var el = $(this), off = el.data("offset");
          el.css({top: off.top + dt, left: off.left + dl});
     });
},
We are creating the variable dt on the second line there and this value is equal to ui.position.top – offset.top and we are also creating the variable dl that is dl = ui.position.left – offset.left. So we have:
  • var dlworking with the x axis or the left coordinates
  • var dtworking with the y axis or the top coordinates
Lets add a console.log to see what these values are before we do the math. Add the following code to see what our variables and math are doing:
console.log("The value of dt is "+dt+" and is equal to "+ui.position.top+" - "+offset.top);
console.log("The value of dl is "+dl+" and is equal to "+ui.position.left+" - "+offset.left);
console.log("The value of ui.position.top is "+ui.position.top);
console.log("The value of ui.position.left is "+ui.position.left);
console.log("The value of offset.left is "+offset.top);
console.log("The value of offset.left is "+offset.left);
When you run the code the console.log() outputs the following:
The value of dt is 37 and is equal to 237 - 200
The value of dl is 152 and is equal to 352 - 200
The value of ui.position.top is 237
The value of ui.position.left is 352
The value of offset.top is 200
The value of offset.left is 200
Notice what the code is printing out, it is taking the ui.position.top and subtracting the value of offset.top and giving us the difference to equal variable dt. We do this math so we can update the top and left CSS properties in the next section of code, if we didn’t do this math, we would select and drag our elements and they would move sporadically on the page.
Next we are going to cover the other each function that loops through each of the selected elements expect $(“this”):
// take all the elements that are selected expect $("this"), which is the element being dragged and loop through each.
selected.not(this).each(function() {
     // create the variable for we don't need to keep calling $("this")
     // el = current element we are on
     // off = what position was this element at when it was selected, before drag
     var el = $(this), off = el.data("offset");
     el.css({top: off.top + dt, left: off.left + dl});
});
So we have the last big piece of code to make this script work. Like I said, you have the each function that runs through each element expect $(“this”), then we create two variables:
  • elwhich is the current element we are on
  • offwhich is the position of the elements when they were selected, before any type of movement and drag
The last segment: we are going to be adding or subtracting (we will subtract if the dt or dl is negative). The dl stands for delta left and dt stands for delta top. For instance lets set something up:
The current element we are on start at the coordinates: 10, 30, now we drag that to: 8, 15. Now lets run the math, the new position of the element is: 2, 15. Say, you drag it again, it runs the loop once again, and the off will be 2, 15 and the new value will be wherever the new coordinates are subtract the total delta from when the drag started until now, not just the last mouse movement.
Now that we did the math and we have captured the new value, update it is the css property and plug in the top and left coordinates.