Last active
January 26, 2023 07:50
-
-
Save c-kick/a3a9d0adf22cc921eb03 to your computer and use it in GitHub Desktop.
jQuery - Collision detection for absolute positioned elements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jQuery Collision Detection - v1.0 - 1/7/2014 | |
* http://www.hnldesign.nl/work/code/collision-prevention-using-jquery/ | |
* | |
* Copyright (c) 2014 HN Leussink | |
* Dual licensed under the MIT and GPL licenses. | |
* | |
* Example: http://code.hnldesign.nl/demo/hnl.collision.detection.html | |
*/ | |
(function ($, document, window) { | |
"use strict"; | |
function CollisionDetection(el, opts) { | |
this.container = $(el); | |
this.colliders = this.container.children().removeData('level'); | |
this.defaults = { | |
levelMemory: {level: [], levelObjects: []}, | |
spacing: 1 | |
}; | |
this.opts = $.extend(this.defaults, opts); | |
this.init(); | |
} | |
CollisionDetection.prototype.init = function () { | |
var o = this.opts, t = this; | |
t.process(t.colliders); | |
}; | |
CollisionDetection.prototype.sort = function (els) { | |
var o = this.opts, t = this, x = els.sort(function (a, b) { | |
//sort elements by left positioning | |
var a_left = $(a).position().left, b_left = $(b).position().left, ret; | |
if (a_left < b_left) { | |
ret = -1; | |
} else if (a_left > b_left) { | |
ret = 1; | |
} else { | |
ret = 0; | |
} | |
return ret; | |
}).detach(); | |
//reattach elements | |
t.container.append(x); | |
}; | |
CollisionDetection.prototype.leveler = function (els) { | |
var o = this.opts, t = this; | |
els.each(function (i) { | |
var this_ele = $(this), | |
next_ele = this_ele.next(); | |
var this_props = { | |
'height': this_ele.outerHeight(false), | |
'left': this_ele.position().left, | |
'width': this_ele.outerWidth(false) | |
}; | |
var next_props = (next_ele.length > 0) ? { | |
'height': next_ele.outerHeight(false), | |
'left': next_ele.position().left, | |
'width': next_ele.outerWidth(false) | |
} : null; | |
var thisLevel = parseInt(this_ele.data('level'), 10), newLevel; | |
if (isNaN(thisLevel)) { | |
thisLevel = 0; | |
this_ele.data('level', thisLevel); | |
} | |
//store amount of pixels 'filled' in level | |
o.levelMemory.level[thisLevel] = (this_props.left + this_props.width); | |
//level the next element | |
if (next_ele.length > 0) { | |
if ((this_props.left + this_props.width) > next_props.left) { | |
$.each(o.levelMemory.level, function (level, filled) { | |
if (filled < next_props.left) { | |
newLevel = level; | |
return false; //break out of loop | |
} | |
}); | |
if (newLevel === undefined) { | |
newLevel = o.levelMemory.level.length; | |
} | |
} | |
next_ele.data('level', newLevel); | |
} | |
//push element into the right level object | |
if (!o.levelMemory.levelObjects[thisLevel]) { | |
o.levelMemory.levelObjects[thisLevel] = []; | |
} | |
o.levelMemory.levelObjects[thisLevel].push(this_ele); | |
}); | |
}; | |
CollisionDetection.prototype.setDimensions = function () { | |
var o = this.opts, t = this, prevHeight = 0; | |
//set each level to the correct css bottom value | |
$(o.levelMemory.levelObjects).each(function (i) { | |
prevHeight += o.spacing; | |
var level = $(this).map(function () {return this.toArray(); }), | |
thisHeight = Math.max.apply(null, $(this).map(function () { return $(this).outerHeight(false); })); | |
level.css('bottom', i === 0 ? 0 : prevHeight); | |
prevHeight += thisHeight; | |
}); | |
//set container to match height of elements inside | |
t.container.css({ | |
height: prevHeight | |
}); | |
}; | |
CollisionDetection.prototype.process = function (els) { | |
var o = this.opts, t = this; | |
//sort elements based on their appearance (left css property) | |
t.sort(els); | |
//arrange elements into levels | |
t.leveler(els); | |
//set dimensions | |
t.setDimensions(); | |
}; | |
$.fn.CollisionDetection = function (opts) { | |
return this.each(function () { | |
new CollisionDetection(this, opts); | |
}); | |
}; | |
})(jQuery, document, window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool, but it's a pity it doesn't work (the demo - plenty of collisions)