Permalink
Browse files

icholy ghost merge

  • Loading branch information...
1 parent 6219ab4 commit 8978b69d7a6ce0d4912afa2ec7f55a0d1f2350b3 @kristianmandrup committed Aug 13, 2012
Showing with 99 additions and 103 deletions.
  1. +7 −3 index.html
  2. +92 −100 jquery.masonry.js
View
@@ -3,7 +3,7 @@
<head>
<title>Masonry Drag and Drop</title>
<style type="text/css">
- .box-item {
+ .box-item {
width: 100px;
height: 100px;
float: left;
@@ -17,11 +17,15 @@
cursor: move;
}
+ .drag-ghost {
+ opacity: 0.5;
+ z-index: 0;
+ }
+
.color1 { background-color: blue; z-index: 9999;}
.color2 { background-color: green;}
.bigger { height: 150px; }
- .smaller { height: 75px; width: 200px; }
- .drag-ghost { background-color: orange; }
+ .smaller { height: 75px; width: 200px; }
</style>
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/jquery.event.drag-2.2.js"></script>
View
@@ -82,10 +82,7 @@
isFitWidth: false,
containerStyle: {
position: 'relative'
- },
- wastedSpaceJitter: 75,
- wastedSpacePenalty: 30,
- yJitter: 72
+ }
};
$.Mason.prototype = {
@@ -163,7 +160,6 @@
_init : function( callback ) {
this._getColumns();
this._reLayout( callback );
- this.element.trigger( "masonry.columncountchange", [this.cols] );
},
option: function( key, value ){
@@ -179,29 +175,11 @@
// used on collection of atoms (should be filtered, and sorted before )
// accepts atoms-to-be-laid-out to start with
layout : function( $bricks, callback ) {
- this.element.trigger('masonry.beforelayout');
// place each brick
for (var i=0, len = $bricks.length; i < len; i++) {
this._placeBrick( $bricks[i] );
}
- var maxY = Math.max.apply( Math, this.colYs ) + this.offset.y, wastedSpaceItem, wastedSpace = [];
- for (var i=0, len = this.colYs.length; i < len; i++) {
- var wastedHeight = maxY - this.colYs[i] - this.offset.y;
- if ( wastedHeight ) {
- // get the top, height, width, and right/left of a box that takes up the entire area of wasted space.
- var wastedSpaceItem = {
- top: this.colYs[i] + this.offset.y,
- height: wastedHeight,
- width: this.columnWidth
- };
- wastedSpaceItem[ this.horizontalDirection ] = this.columnWidth * i + this.offset.x;
- wastedSpace.push(wastedSpaceItem);
- }
- }
- if ( wastedSpace.length ) {
- this.element.trigger( "masonry.wastedspace", [wastedSpace] );
- }
// set the size of the container
var containerSize = {};
@@ -221,17 +199,6 @@
}
this.styleQueue.push({ $el: this.element, style: containerSize });
- this._processStyleQueue();
-
- // provide $elems as context for the callback
- if ( callback ) {
- callback.call( $bricks );
- }
-
- this.isLaidOut = true;
- this.element.trigger( "masonry.complete", [wastedSpace] );
- },
- _processStyleQueue: function() {
// are we animating the layout arrangement?
// use plugin-ish syntax for css or animate
var styleFn = !this.isLaidOut ? 'css' : (
@@ -241,20 +208,27 @@
// process styleQueue
var obj;
- for (var i=0, len = this.styleQueue.length; i < len; i++) {
+ for (i=0, len = this.styleQueue.length; i < len; i++) {
obj = this.styleQueue[i];
obj.$el[ styleFn ]( obj.style, animOpts );
}
// clear out queue for next time
this.styleQueue = [];
+
+ // provide $elems as context for the callback
+ if ( callback ) {
+ callback.call( $bricks );
+ }
+
+ this.isLaidOut = true;
},
+
// calculates number of columns
// i.e. this.columnWidth = 200
_getColumns : function() {
var container = this.options.isFitWidth ? this.element.parent() : this.element,
- containerWidth = container.width(),
- containerPadding = this.element.outerWidth() - this.element.width();
+ containerWidth = container.width();
// use fluid columnWidth function if there
this.columnWidth = this.isFluid ? this.options.columnWidth( containerWidth ) :
@@ -267,15 +241,15 @@
this.columnWidth += this.options.gutterWidth;
- this.cols = Math.floor( ( containerWidth + this.options.gutterWidth - containerPadding ) / this.columnWidth );
+ this.cols = Math.floor( ( containerWidth + this.options.gutterWidth ) / this.columnWidth );
this.cols = Math.max( this.cols, 1 );
},
// layout logic
_placeBrick: function( brick ) {
var $brick = $(brick),
- colSpan, groupCount, groupY, groupColY, j, k, wastedY;
+ colSpan, groupCount, groupY, groupColY, j;
//how many columns does this brick span
colSpan = Math.ceil( $brick.outerWidth(true) / this.columnWidth );
@@ -284,91 +258,48 @@
if ( colSpan === 1 ) {
// if brick spans only one column, just like singleMode
groupY = this.colYs;
- // it's impossible for a single column brick to waste space, so fill the wastedY array with zeros.
- wastedY = [];
- for ( var i=0; i < this.colYs.length; i++) wastedY[i] = 0;
} else {
// brick spans more than one column
// how many different places could this brick fit horizontally
groupCount = this.cols + 1 - colSpan;
groupY = [];
- wastedY = [];
// for each group potential horizontal position
for ( j=0; j < groupCount; j++ ) {
// make an array of colY values for that one group
groupColY = this.colYs.slice( j, j+colSpan );
// and get the max value of the array
groupY[j] = Math.max.apply( Math, groupColY );
- // find out how much space each column option would waste
- wastedY[j] = 0;
- for( k=0; k < groupColY.length; k++ ) {
- wastedY[j] += (groupY[j] - groupColY[k]);
- }
}
+
}
- // get the minimum wasted Y value from the columns
+ // get the minimum Y value from the columns
var minimumY = Math.min.apply( Math, groupY ),
- minimumWasted = Math.min.apply( Math, wastedY ),
- shortCol = 0,
- potentialColumns = [],
- potentialY = [];
+ shortCol = 0;
- // find the columns that waste the minimum amount of space
- for (var i=0, len = wastedY.length; i < len; i++) {
- var spaceBetweenThisYandMinimum = groupY[i] - minimumY;
- var wastedSpacePenalty = spaceBetweenThisYandMinimum * this.options.wastedSpacePenalty;
- //console.log( wastedSpacePenalty, brick );
- if ( wastedY[i] / colSpan <= minimumWasted + this.options.wastedSpaceJitter - wastedSpacePenalty) {
- potentialColumns.push(i);
- potentialY.push(groupY[i]);
- }
- }
- if (potentialColumns.length === 0) {
- for (var i=0, len = groupY.length+1; i < len; i++) {
- potentialColumns.push(i);
- }
- potentialY = groupY;
- }
-
- // find the shortest, leftmost column
- minimumY = Math.min.apply( Math, potentialY );
- for (var i=0, len = potentialColumns.length; i < len; i++) {
- if ( potentialY[i] <= minimumY + this.options.yJitter ) {
- shortCol = potentialColumns[i];
+ // Find index of short column, the first from the left
+ for (var i=0, len = groupY.length; i < len; i++) {
+ if ( groupY[i] === minimumY ) {
+ shortCol = i;
break;
}
}
+
// position the brick
var position = {
- top: groupY[shortCol] + this.offset.y
+ top: minimumY + this.offset.y
};
// position.left or position.right
position[ this.horizontalDirection ] = this.columnWidth * shortCol + this.offset.x;
this.styleQueue.push({ $el: $brick, style: position });
- // apply setHeight to necessary columns, triggering wastedspace event if needed.
- var setHeight = groupY[shortCol] + $brick.outerHeight(true),
- setSpan = this.cols + 1 - groupY.length,
- wastedSpaceItem, wastedSpace = [];
+ // apply setHeight to necessary columns
+ var setHeight = minimumY + $brick.outerHeight(true),
+ setSpan = this.cols + 1 - len;
for ( i=0; i < setSpan; i++ ) {
- var wastedHeight = position.top - this.colYs[ shortCol + i ] - this.offset.y;
- if ( wastedHeight ) {
- // get the top, height, width, and right/left of a box that takes up the entire area of wasted space.
- wastedSpaceItem = {
- top: this.colYs[ shortCol + i ] + this.offset.y,
- height: wastedHeight,
- width: this.columnWidth
- };
- wastedSpaceItem[ this.horizontalDirection ] = this.columnWidth * (shortCol+i) + this.offset.x;
- wastedSpace.push(wastedSpaceItem)
- }
this.colYs[ shortCol + i ] = setHeight;
}
- if (wastedSpace.length) {
- this.element.trigger( "masonry.wastedspace", [wastedSpace] );
- }
},
@@ -379,7 +310,6 @@
this._getColumns();
if ( this.isFluid || this.cols !== prevColCount ) {
// if column count has changed, trigger new layout
- this.element.trigger( "masonry.columncountchange", [this.cols] );
this._reLayout();
}
},
@@ -527,16 +457,38 @@
return closest;
},
+ _createGhostBrick : function($brick){
+
+ var closest = this._getClosestBrick($brick),
+ $ghost = $brick.clone().html('').addClass('drag-ghost'),
+ pos = $brick.position();
+
+ $ghost.css({
+ width : $brick.width(),
+ height : $brick.height()
+ });
+
+ this.$bricks.splice(closest.index, 0, $ghost[0]);
+ this.element.append($ghost);
+ this._reLayout();
+
+ return closest.index;
+ },
+
_initDrag : function($bricks){
var _this = this,
dragged = null,
- pos, closest;
+ pos, closest,
+ ghostInterval = null,
+ ghostIndex = -1,
+ ghostTime, ghostReset;
$bricks.bind('dragstart', function(e) {
// make sure we're dragging by the right thing
- if(_this.options.dragHandleSelector !== null && !$(e.target).is(_this.options.dragHandleSelector)){
+ if(_this.options.dragHandleSelector !== null
+ && !$(e.target).is(_this.options.dragHandleSelector)){
return false;
}
@@ -552,25 +504,65 @@
_this.$bricks = _this.$bricks.not(this);
_this._reLayout();
+ ghostTime = ghostReset = new Date().getTime();
+
+ ghostInterval = setInterval(function(){
+ if(ghostReset !== ghostTime){
+ if(ghostIndex !== -1){
+
+ // this kinda sucks because it doesn't use the original
+ // position of the bricks
+ if(_this._getClosestBrick($(dragged)).index === ghostIndex){
+ return;
+ }
+
+ $(_this.$bricks.splice(ghostIndex,1)).fadeOut(function(){
+ $(this).remove();
+ });
+ ghostIndex = -1;
+ _this._reLayout();
+ }
+ if(new Date().getTime() - ghostReset > 200){
+ ghostIndex = _this._createGhostBrick($(dragged));
+ ghostTime = ghostReset;
+ }
+ }
+ }, 100);
+
}).bind('drag', function(e, dd) {
$(this).css({
top : pos.top + dd.deltaY,
left : pos.left + dd.deltaX
});
+ ghostReset = new Date().getTime();
+
}).bind('dragend', function(e) {
-
+
+ // clear the ghosting interval
+ clearInterval(ghostInterval);
+
// remove the dragClass
if(_this.options.dragClass !== null){
$(this).removeClass(_this.options.dragClass);
}
// insert the brick back into the array
- closest = _this._getClosestBrick(dragged);
- _this.$bricks.splice(closest.index , 0, dragged);
+ if(ghostIndex !== -1) {
+ var $ghost = $(_this.$bricks[ghostIndex]);
+ $ghost.fadeOut(function(){
+ $ghost.remove();
+ });
+ _this.$bricks[ghostIndex] = dragged;
+ ghostIndex = -1;
+ } else {
+ closest = _this._getClosestBrick(dragged);
+ _this.$bricks.splice(closest.index , 0, dragged);
+ }
dragged = null;
+
_this._reLayout();
});
}

0 comments on commit 8978b69

Please sign in to comment.