summaryrefslogtreecommitdiff
path: root/templates/project/assets/javascripts/gridster/jquery.collision.js
diff options
context:
space:
mode:
Diffstat (limited to 'templates/project/assets/javascripts/gridster/jquery.collision.js')
-rwxr-xr-xtemplates/project/assets/javascripts/gridster/jquery.collision.js224
1 files changed, 224 insertions, 0 deletions
diff --git a/templates/project/assets/javascripts/gridster/jquery.collision.js b/templates/project/assets/javascripts/gridster/jquery.collision.js
new file mode 100755
index 0000000..5d37c61
--- /dev/null
+++ b/templates/project/assets/javascripts/gridster/jquery.collision.js
@@ -0,0 +1,224 @@
+/*
+ * jquery.collision
+ * https://github.com/ducksboard/gridster.js
+ *
+ * Copyright (c) 2012 ducksboard
+ * Licensed under the MIT licenses.
+ */
+
+;(function($, window, document, undefined){
+
+ var defaults = {
+ colliders_context: document.body
+ // ,on_overlap: function(collider_data){},
+ // on_overlap_start : function(collider_data){},
+ // on_overlap_stop : function(collider_data){}
+ };
+
+
+ /**
+ * Detects collisions between a DOM element against other DOM elements or
+ * Coords objects.
+ *
+ * @class Collision
+ * @uses Coords
+ * @param {HTMLElement} el The jQuery wrapped HTMLElement.
+ * @param {HTMLElement|Array} colliders Can be a jQuery collection
+ * of HTMLElements or an Array of Coords instances.
+ * @param {Object} [options] An Object with all options you want to
+ * overwrite:
+ * @param {Function} [options.on_overlap_start] Executes a function the first
+ * time each `collider ` is overlapped.
+ * @param {Function} [options.on_overlap_stop] Executes a function when a
+ * `collider` is no longer collided.
+ * @param {Function} [options.on_overlap] Executes a function when the
+ * mouse is moved during the collision.
+ * @return {Object} Collision instance.
+ * @constructor
+ */
+ function Collision(el, colliders, options) {
+ this.options = $.extend(defaults, options);
+ this.$element = el;
+ this.last_colliders = [];
+ this.last_colliders_coords = [];
+ if (typeof colliders === 'string' || colliders instanceof jQuery) {
+ this.$colliders = $(colliders,
+ this.options.colliders_context).not(this.$element);
+ }else{
+ this.colliders = $(colliders);
+ }
+
+ this.init();
+ }
+
+
+ var fn = Collision.prototype;
+
+
+ fn.init = function() {
+ this.find_collisions();
+ };
+
+
+ fn.overlaps = function(a, b) {
+ var x = false;
+ var y = false;
+
+ if ((b.x1 >= a.x1 && b.x1 <= a.x2) ||
+ (b.x2 >= a.x1 && b.x2 <= a.x2) ||
+ (a.x1 >= b.x1 && a.x2 <= b.x2)
+ ) { x = true; }
+
+ if ((b.y1 >= a.y1 && b.y1 <= a.y2) ||
+ (b.y2 >= a.y1 && b.y2 <= a.y2) ||
+ (a.y1 >= b.y1 && a.y2 <= b.y2)
+ ) { y = true; }
+
+ return (x && y);
+ };
+
+
+ fn.detect_overlapping_region = function(a, b){
+ var regionX = '';
+ var regionY = '';
+
+ if (a.y1 > b.cy && a.y1 < b.y2) { regionX = 'N'; }
+ if (a.y2 > b.y1 && a.y2 < b.cy) { regionX = 'S'; }
+ if (a.x1 > b.cx && a.x1 < b.x2) { regionY = 'W'; }
+ if (a.x2 > b.x1 && a.x2 < b.cx) { regionY = 'E'; }
+
+ return (regionX + regionY) || 'C';
+ };
+
+
+ fn.calculate_overlapped_area_coords = function(a, b){
+ var x1 = Math.max(a.x1, b.x1);
+ var y1 = Math.max(a.y1, b.y1);
+ var x2 = Math.min(a.x2, b.x2);
+ var y2 = Math.min(a.y2, b.y2);
+
+ return $({
+ left: x1,
+ top: y1,
+ width : (x2 - x1),
+ height: (y2 - y1)
+ }).coords().get();
+ };
+
+
+ fn.calculate_overlapped_area = function(coords){
+ return (coords.width * coords.height);
+ };
+
+
+ fn.manage_colliders_start_stop = function(new_colliders_coords, start_callback, stop_callback){
+ var last = this.last_colliders_coords;
+
+ for (var i = 0, il = last.length; i < il; i++) {
+ if ($.inArray(last[i], new_colliders_coords) === -1) {
+ start_callback.call(this, last[i]);
+ }
+ }
+
+ for (var j = 0, jl = new_colliders_coords.length; j < jl; j++) {
+ if ($.inArray(new_colliders_coords[j], last) === -1) {
+ stop_callback.call(this, new_colliders_coords[j]);
+ }
+
+ }
+ };
+
+
+ fn.find_collisions = function(player_data_coords){
+ var self = this;
+ var colliders_coords = [];
+ var colliders_data = [];
+ var $colliders = (this.colliders || this.$colliders);
+ var count = $colliders.length;
+ var player_coords = self.$element.coords()
+ .update(player_data_coords || false).get();
+
+ while(count--){
+ var $collider = self.$colliders ?
+ $($colliders[count]) : $colliders[count];
+ var $collider_coords_ins = ($collider.isCoords) ?
+ $collider : $collider.coords();
+ var collider_coords = $collider_coords_ins.get();
+ var overlaps = self.overlaps(player_coords, collider_coords);
+
+ if (!overlaps) {
+ continue;
+ }
+
+ var region = self.detect_overlapping_region(
+ player_coords, collider_coords);
+
+ //todo: make this an option
+ if (region === 'C'){
+ var area_coords = self.calculate_overlapped_area_coords(
+ player_coords, collider_coords);
+ var area = self.calculate_overlapped_area(area_coords);
+ var collider_data = {
+ area: area,
+ area_coords : area_coords,
+ region: region,
+ coords: collider_coords,
+ player_coords: player_coords,
+ el: $collider
+ };
+
+ if (self.options.on_overlap) {
+ self.options.on_overlap.call(this, collider_data);
+ }
+ colliders_coords.push($collider_coords_ins);
+ colliders_data.push(collider_data);
+ }
+ }
+
+ if (self.options.on_overlap_stop || self.options.on_overlap_start) {
+ this.manage_colliders_start_stop(colliders_coords,
+ self.options.on_overlap_stop, self.options.on_overlap_start);
+ }
+
+ this.last_colliders_coords = colliders_coords;
+
+ return colliders_data;
+ };
+
+
+ fn.get_closest_colliders = function(player_data_coords){
+ var colliders = this.find_collisions(player_data_coords);
+ var min_area = 100;
+ colliders.sort(function(a, b){
+ if (a.area <= min_area) {
+ return 1;
+ }
+
+ /* if colliders are being overlapped by the "C" (center) region,
+ * we have to set a lower index in the array to which they are placed
+ * above in the grid. */
+ if (a.region === 'C' && b.region === 'C') {
+ if (a.coords.y1 < b.coords.y1 || a.coords.x1 < b.coords.x1) {
+ return - 1;
+ }else{
+ return 1;
+ }
+ }
+
+ if (a.area < b.area){
+ return 1;
+ }
+
+ return 1;
+ });
+ return colliders;
+ };
+
+
+ //jQuery adapter
+ $.fn.collision = function(collider, options) {
+ return new Collision( this, collider, options );
+ };
+
+
+}(jQuery, window, document));