Reputation: 33
I'm trying to get columns in a bootstrap row to snap-resize incrementally to their respective column sizes by dragging either way. They must always add up to 12 columns.
See an example of what I'm trying to achieve
The closest example of what I need is here: http://jsfiddle.net/onigetoc/ag4mgpbs/ however the columns around them do not resize larger or smaller depending on the column next to them.
I have looked at using [gridstack.js to achieve this, but I can't get the logic of adding or subtracting columns correctly with basic jQuery/jQuery UI.
The code I've written I'm sure is going in the wrong direction, I can't work out why the columns don't add up when I expect them to, it might be something to do with the events I'm using.
var oldColNum = 0;
var nextColFraction = 0;
$('.column').resizable({
handles: 'e',
containment: 'parent',
start: function (e, ui) {
var nextCol = $(this).nextAll('.column').get(0);
nextColFraction = $(nextCol).data('fraction');
$(this).closest('.row').find('.column').css("width", '');
},
resize: function (e, ui) {
// console.clear();
/**
* The Column currently being resized
*/
var thisCol = ui.element;
oldColNum = thisCol.data('fraction');
/**
* The parenting row
*/
var parentRow = thisCol.closest('.row');
/**
* The Other Columns
*/
var nextCol = thisCol.nextAll('.column').get(0);
var otherCols = parentRow.find('.column').not(thisCol);
var otherColFractions = [];
otherCols.each(function () {
otherColFractions.push($(this).data('fraction'));
});
var totalOtherFractions = otherColFractions.reduce(function(a, b) { return a + b }, 0);
/**
* Work out the percentage width it currently is
*/
var cellPercentWidth = (100 * thisCol.outerWidth() / parentRow.outerWidth());
/**
* Change the class to the one that best suits the current size
*/
var colNum = getClosest(gridSystem, cellPercentWidth);
console.log(colNum, ui.originalElement.data('fraction'));
if (colNum < ui.originalElement.data('fraction')) {
nextColFraction++;
$(nextCol).removeClass(bsClass)
.addClass('col-md-' + nextColFraction)
.attr('data-fraction', nextColFraction);
}
if (colNum > ui.originalElement.data('fraction')) {
nextColFraction--;
$(nextCol).removeClass(bsClass)
.addClass('col-md-' + nextColFraction)
.attr('data-fraction', nextColFraction);
}
thisCol.removeClass(bsClass)
.addClass('col-md-' + colNum)
.attr('data-fraction', colNum);
thisCol.css("width", '');
}
});
});
// Bootstrap grid system array
var gridSystem = [
{grid: 8.33333333, col: 1},
{grid: 16.66666667, col: 2},
{grid: 25, col: 3},
{grid: 33.33333333, col: 4},
{grid: 41.66666667, col: 5},
{grid: 50, col: 6},
{grid: 58.33333333, col: 7},
{grid: 66.66666667, col: 8},
{grid: 75, col: 9},
{grid: 83.33333333, col: 10},
{grid: 91.66666667, col: 11},
{grid: 100, col: 12}
];
// find the closest number from Bootstrap grid
function getClosest(arr, value) {
var closest, mindiff = null;
for (var i = 0; i < arr.length; ++i) {
var diff = Math.abs(arr[i].grid - value);
if (mindiff === null || diff < mindiff) {
// first value or trend decreasing
closest = i;
mindiff = diff;
} else {
return arr[closest]['col']; // col number
}
}
return null;
}
Any help would be greatly appreciated.
Upvotes: 3
Views: 2251
Reputation: 3565
NOTE: This is more of a clarification than an answer, but too much code to put in a comment.
The getClosest function does not cover the case where an element is more than 11 cols. I changed the following part:
function getClosest(arr, value) {
var closest, mindiff = null;
for (var i = 0; i < arr.length; ++i) {
var diff = Math.abs(arr[i].grid - value);
if (mindiff === null || diff < mindiff) {
// first value or trend decreasing
closest = i;
mindiff = diff;
} else {
// trend will increase from this point onwards
//return arr[closest]; //object
return arr[closest]['col']; // col number
//return arr[closest]['grid']; // col percentage
}
}
return null;
}
to:
function getClosest(arr, value) {
let closest, mindiff = null;
for (let i = 0; i < arr.length; ++i) {
let diff = Math.abs(arr[i].grid - value);
if (i === arr.length - 1 && value >= 95) {
// No other matches, cap at last size
return arr[i]['col']; // col number
} else if (mindiff === null || diff < mindiff) {
// First value or trend decreasing
closest = i;
mindiff = diff;
} else {
return arr[closest]['col']; // col number
}
}
// Invalid
return null;
}
Upvotes: 0
Reputation: 73
You would find the next column after it that has the grid class and remove one from it.
$(function() {
var bsClass = "col-sm-1 col-sm-2 col-sm-3 col-sm-4 col-sm-5 col-sm-6 col-sm-7 col-sm-8 col-sm-9 col-sm-10 col-sm-11 col-sm-12";
$(document).ready(function() {
$('.mb-grid-item').resizable({
handles: "e",
resize: function(e, ui) {
console.log('resizable');
var thiscol = $(this);
var currentNumberBefore = parseInt(thiscol.attr('class').match(/col-sm-(\d+)/)[1]);
var container = thiscol.parent();
var cellPercentWidth = 100 * ui.originalElement.outerWidth() / container.innerWidth();
// ui.originalElement.css('width', cellPercentWidth + '%');
var newColNum = getClosest(gridsystem, cellPercentWidth);
var thiscol = $(this);
thiscol.css("width", '');
//thiscol.removeAttr("style");
thiscol.find(".showClass").text('col-sm-' + newColNum);
//alert(cellPercentWidth);
var currentTopPosition = thiscol.position().top
var nextColumn = thiscol.next('.mb-grid-item');
var nextTopPosition = nextColumn.position().top;
if(currentNumberBefore !== newColNum && nextColumn && nextTopPosition === currentTopPosition) {
try {
var nextNumber = nextColumn.attr('class').match(/col-sm-(\d+)/)[1];
if(nextNumber) {
nextNumber = parseInt(nextNumber);
if((nextNumber+1) > 0) {
nextColumn.removeClass(bsClass);
var nextColumnNumber
if(currentNumberBefore > newColNum) {
nextColumnNumber = nextNumber+1;
} else {
if(nextNumber-1 > 0) {
nextColumnNumber = nextNumber-1;
} else {
nextColumnNumber = nextNumber;
}
}
var nextClass = 'col-sm-' + nextColumnNumber.toString();
nextColumn.find(".showClass").text(nextClass);
nextColumn.addClass(nextClass);
}
}
} catch(err) {
console.log('err', err);
}
}
thiscol.removeClass(bsClass).addClass('col-sm-' + newColNum);
}
}
);
}); //ready end
});
/***********************/
// Bootstrap grid system array
var gridsystem = [{
grid: 8.33333333,
col: 1
}, {
grid: 16.66666667,
col: 2
}, {
grid: 25,
col: 3
}, {
grid: 33.33333333,
col: 4
}, {
grid: 41.66666667,
col: 5
}, {
grid: 50,
col: 6
}, {
grid: 58.33333333,
col: 7
}, {
grid: 66.66666667,
col: 8
}, {
grid: 75,
col: 9
}, {
grid: 83.33333333,
col: 10
}, {
grid: 100,
col: 11
}, {
grid: 91.66666667,
col: 12
}, {
grid: 10000,
col: 10000
}];
// find the closest number from Bootstrap grid
function getClosest(arr, value) {
var closest, mindiff = null;
for (var i = 0; i < arr.length; ++i) {
var diff = Math.abs(arr[i].grid - value);
if (mindiff === null || diff < mindiff) {
// first value or trend decreasing
closest = i;
mindiff = diff;
} else {
// trend will increase from this point onwards
//return arr[closest]; //object
return arr[closest]['col']; // col number
//return arr[closest]['grid']; // col percentage
}
}
return null;
}
```
Upvotes: 1