views:

54

answers:

2

Hi chaps,

I'm trying to translate Brandon Kelly's AC.VR class (Prototype) into a jQuery plugin.

Here is a link to his example (unfortunately just working in Safari).

I managed to get the basics working. The problem I'm having is the mouse event history for the velocity, acceleration and friction part of the script.

Here is a shorten extract of his Prototype code:

.
.
.
makeInteractive: function(){
    this.bindGrabStart = this.onGrabStart.bind(this);
    this.bindGrabChange = this.onGrabChange.bind(this);
    this.bindGrabEnd = this.onGrabEnd.bind(this);
},
onGrabStart: function(event){
    this.grabHistory = $A([ event ]);
    this.grabHistoryInterval = setInterval(this.updateGrabHistory.bind(this), 10);
},
onGrabChange: function(event){
    this.onGrabChange.clientX = event.clientX;
    this.onGrabChange.clientY = event.clientY;
},
updateGrabHistory: function(){
    var func = this.onGrabChange.clientX ? this.onGrabChange : this.onGrabStart;
    this.grabHistory.unshift({ clientX: func.clientX, clientY: func.clientY });
    if (this.grabHistory.length > 3) {
        this.grabHistory.splice(3);
    }
},
.
.
.

and here is my jQuery translation:

.
.
.
var makeInteractive = function(){
    $(document).bind("mousedown", function(event) { obj.onGrabStart(event) }, false);
    $(document).bind("mousemove", function(event) { obj.onGrabChange(event) }, false);
    $(document).bind("mouseup", function(event) { obj.onGrabEnd(event) }, false);
}

this.onGrabStart = function(event){
  ???
}

this.onGrabChange = function(event){
    this.onGrabChange.clientX = event.clientX;
    this.onGrabChange.clientY = event.clientY;
};

this.updateGrabHistory = function(event){
    var func = this.onGrabChange.clientX ? this.onGrabChange : this.onGrabStart;
    this.grabHistory.filter({ clientX: func.clientX, clientY: func.clientY });
    if (this.grabHistory.length > 3) {
        this.grabHistory.splice(3);
    }
};
.
.
.

Basically the question is: How can I deal with the grabHistory (array object ?) in jQuery?

This line confuses me most:

this.grabHistory = $A([ event ]);

I just found this page which explains a bit about the $A function: http://www.learn-javascript-tutorial.com/PrototypeJS.cfm#Dollar_A_Function

I'm grateful for every advice.

+1  A: 

The official documentation says:

$A

$A(iterable) → actualArray

Accepts an array-like collection (anything with numeric indices) and returns its equivalent as an actual Array object. This method is a convenience alias of Array.from, but is the preferred way of casting to an Array.

The primary use of $A is to obtain an actual Array object based on anything that could pass as an array (e.g. the NodeList or HTMLCollection objects returned by numerous DOM methods, or the predefined arguments reference within your functions).

The reason you would want an actual Array is simple: Prototype extends Array to equip it with numerous extra methods, and also mixes in the Enumerable module, which brings in another boatload of nifty methods. Therefore, in Prototype, actual Arrays trump any other collection type you might otherwise get.

This sounds like a very Prototype specific usage, which is probably unnecessary to translate 1:1 to jQuery. In jQuery the jQuery object itself holds all the powerful methods and the difference between array-like collections and Array-instances is usually not important.

deceze
+1  A: 

The line that confuses you more, is actually using $A where isn't needed, it can be removed safely:

this.grabHistory = [event];

$A is a helper function to produce a real array from an array-like object such a DOMCollection, or an arguments object for example.

The expression $A([event]) is simply redundant, since you are actually constructing a real array, which has one element, the event object -the literal [event] does that-.

The term array-like means an object that contains numeric properties and a length property, but is not really an array - it doesn't inherit the methods from Array.prototype -.

Anyway, the implementation of the $A function is quite simple (you can see the actual PrototypeJS implementation here):

function toArray(obj) {
  var array = [];
  // iterate backwards ensuring that length is an UInt32
  for (var i = obj.length >>> 0; i--;) { 
    array[i] = obj[i];
  }
  return array;
}
CMS