Skip to content

Instantly share code, notes, and snippets.

@jpic
Created February 1, 2013 13:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpic/4691211 to your computer and use it in GitHub Desktop.
Save jpic/4691211 to your computer and use it in GitHub Desktop.
KISS jQuery plugin for table column reorganisation via drag'n'drop. Requires jquery-ui with draggable and droppable support of course.
{% block extra_head %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}fusion/table.css" />
{% endblock %}
{% block extra_body %}
{% block jquery_ui %}
<script src="{{ STATIC_URL }}fusion/jquery-ui.js" type="text/javascript"></script>
{% endblock %}
<script type="text/javascript" src="{{ STATIC_URL }}fusion/table.js"></script>
<script type="text/javascript">
$('.bloc-content table')
.on('columnMoved', function(e) {
var table = $(this).yourlabsTable();
if (table.xhr) table.xhr.abort();
data = {
columns: [],
};
table.table.find('[data-widget-pk]').each(function() {
if ($(this).parents('table.helper').length) return;
data.columns.push({widget_pk: $(this).data('widget-pk')})
});
table.xhr = $.ajax('{% url 'fusion_list_update' object.pk %}', {
'data': {data: JSON.stringify(data)},
'type': 'POST',
})
})
.yourlabsTable();
});
</script>
{% endblock %}
.dragging {
display: none;
}
.resize-handle {
float: right;
}
.droppable-target {
background-color: green;
}
.helper {
width: 80px;
}
.placeholder {
width: 0px;
}
.placeholder.active {
width: 2px;
background-color: #90EE90;
border-color: #90EE90;
}
.placeholder.usable.active {
background-color: green;
border-color: green;
}
if (window.yourlabs == undefined) window.yourlabs = {};
// Resizing is temporarely disabled because the browser ignores it.
yourlabs.Table = function(table) {
// <table> element.
this.table = table;
// Index of the column being drag.
this.dragIndex = null;
// Index of the column being hovered or drop on.
this.dropIndex = null;
// Resize column handle which will be appended to th.
// this.resizeHandleHtml = '<span class="handle resize-handle"></span>';
// Selector string for resizeHandleHtml.
// this.resizeHandleSelector = '.resize-handle';
// Drag column handle which will be prepended to th.
this.dragHandleHtml = '<span class="handle drag-handle"></span>';
// Selector string for dragHandleHtml.
this.dragHandleSelector = '.drag-handle';
// CSS class for the column being drag. Will be set on all td, ths.
this.dragColumnClass = 'dragging';
// Selector string for the column being drag.
this.dragColumnSelector = '.' + this.dragColumnClass;
// HTML used to create the semi transparent drag helper. It will be filled
// with copies of the contents of the column being drag.
this.helperTableHtml = '<table class="helper">';
// Cell HTML used to create placeholder columns.
this.placeholderHtml = '<td class="placeholder"></td>';
// Selector string for placeholderHtml
this.placeholderSelector = '.placeholder';
// CSS class that should be added to placeholder when they become active.
this.placeholderActiveClass = 'active';
// Selector string for active placeholders
this.placeholderActiveSelector = [
this.placeholderSelector,
'.',
this.placeholderActiveClass
].join('')
}
yourlabs.Table.prototype.initialize = function() {
this.table.find('th')
.prepend(this.dragHandleHtml)
.draggable({
cursor: 'move',
helper: $.proxy(this.dragHelper, this),
start: $.proxy(this.dragStart, this),
stop: $.proxy(this.dragStop, this),
handle: this.dragHandleSelector,
tolerance: 'pointer',
opacity: 0.65,
axis: 'x',
});
this.createPlaceholders();
this.table.find('th, td')
.droppable({
greedy: true,
tolerance: 'pointer',
over: $.proxy(this.dropOver, this),
drop: $.proxy(this.dragStop, this),
});
// this.table.find('th')
// .append(this.resizeHandleHtml)
// $(this.resizeHandleSelector)
// .on('mousedown', $.proxy(this.resizeStart, this))
// $(document)
// .on('mousemove', $.proxy(this.resize, this))
// .on('mouseup', $.proxy(this.resizeStop, this))
// this.createPlaceholders();
}
// yourlabs.Table.prototype.resizeStart = function(e) {
// this.resizing = $(e.currentTarget).parents('th, td');
// this.initialX = e.pageX;
// this.initialWidth = this.resizing.width();
// }
// yourlabs.Table.prototype.resize = function(e) {
// if(this.resizing !== false) {
// $(this.resizing).width(this.initialWidth+(e.pageX-this.initialX));
// }
// }
// yourlabs.Table.prototype.resizeStop = function(e) {
// if(this.resizing !== false) {
// this.resizing = false;
// }
// }
// Remove all placeholder cells.
yourlabs.Table.prototype.removePlaceholders = function() {
this.table.find(this.placeholderSelector).remove()
}
// Create a placeholder column after each actual column.
yourlabs.Table.prototype.createPlaceholders = function() {
this.table.find('th, td').before(this.placeholderHtml);
this.table.find('tr').append(this.placeholderHtml)
}
yourlabs.Table.prototype.dragHelper = function(e) {
this.dragIndex = $(e.currentTarget).index() + 1;
var rows = [];
this.getColumn(this.dragIndex).each(function() {
rows.push('<tr>')
rows.push($('<tr>').html($(this).clone()).html());
rows.push('</tr>')
})
return $(this.helperTableHtml).html(rows.join(''));
}
// On drag start, note the dragged column index and set dragColumnClass.
yourlabs.Table.prototype.dragStart = function(e, ui) {
this.dragIndex = $(e.currentTarget).index() + 1;
this.getColumn(this.dragIndex).addClass(this.dragColumnClass);
}
// On drag stop, get the drop column index, move the cells, trigger columnMoved
// and clean up.
yourlabs.Table.prototype.dragStop = function(e, ui) {
if (this.dragIndex == null) {
// dragStop was already called.
return;
}
this.dropIndex = this.table.find(
this.placeholderActiveSelector + ':first').index();
this.table.find(this.placeholderActiveSelector)
.removeClass(this.placeholderActiveClass)
this.table.find(this.dragColumnSelector)
.removeClass(this.dragColumnClass);
var dragColumn = this.getColumn(this.dragIndex);
var dropColumn = this.getColumn(this.dropIndex);
for (var i=0; i<dragColumn.length; i++) {
$(dragColumn.get(i)).insertAfter(dropColumn.get(i))
}
this.dragIndex = null;
this.dropIndex = null;
this.removePlaceholders();
// Trigger columnMoved while the table is clean from fake columns.
this.table.trigger('columnMoved');
this.createPlaceholders();
}
// Return all cells of a particular column.
yourlabs.Table.prototype.getColumn = function(index) {
return this.table.find(
'td:nth-child(' + index + '), th:nth-child(' + index + ')');
}
// On drop over, update active placeholder.
yourlabs.Table.prototype.dropOver = function(e, ui) {
this.dropIndex = $(e.target).index() + 1;
this.activePlaceholder = this.dropIndex + 1;
this.table.find(this.placeholderSelector)
.removeClass(this.placeholderActiveClass)
this.getColumn(this.activePlaceholder)
.addClass(this.placeholderActiveClass)
}
$.fn.yourlabsTable = function(overrides) {
if (this.length < 1) return;
var overrides = overrides ? overrides : {};
if (this.data('yourlabsTable') == undefined) {
var table = new yourlabs.Table(this);
table = $.extend(table, overrides);
this.data('yourlabsTable', table);
table.initialize();
}
return this.data('yourlabsTable');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment