Drap-n-drop HTML table columns (not rows) - javascript

I've found dragtable http://www.danvk.org/wp/dragtable/ but I need a Jquery-based solution. May be I'm missing something?

The plugin jqGrid (latest versions at github repo) has a feature to re-order columns - the documentation is here. It does not appear to have drag/drop support for re-ordering columns however.
Here is a custom working sample of draggable table columns using only jQuery and jQuery UI sortable interaction.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<script src="jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="jquery-ui-1.8.1.custom.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="jquery-ui-1.8.1.custom.css">
<style type="text/css">
th
{
background-color: #e0e0e0;
cursor: pointer;
}
.ui-state-highlight
{
height: 1.5em;
line-height: 1.2em;
}
</style>
<script type="text/javascript">
$(function() {
var $table1 = $('#table1');
var $table1Thead = $table1.find('thead');
var $table1Tbody = $table1.find('tbody');
var maxCols = 10;
var maxRows = 50;
// populate fake data
for (var i = 1; i <= maxCols; i++) {
$table1Thead.append('<th id="column' + i + '">column ' + i + '</th>');
}
var rowHtml;
for (var x = 1; x <= maxRows; x++) {
rowHtml = '<tr>';
for (var i = 1; i <= maxCols; i++) {
//rowHtml += '<td>row ' + x + ', column ' + i + '</td>';
rowHtml += '<td>column ' + i + '</td>';
}
rowHtml += '</tr>';
$table1Tbody.append(rowHtml);
}
// set an index helper on each th element
$table1Thead.find('th').each(function() {
var thElement = $(this);
thElement.data('columnIndex', $table1Thead.find('th').index(thElement));
});
$table1Thead.sortable({
items: 'th',
containment: 'parent',
helper: 'clone',
placeholder: 'ui-state-highlight',
update: function(event, ui) {
var prevPos = ui.item.data('columnIndex');
var newPos = $table1Thead.find('th').index(ui.item);
// adjust all the row elements
$table1Tbody.find('tr').find('td:eq(' + prevPos + ')').each(function() {
var tdElement = $(this);
var tdElementParent = tdElement.parent();
tdElement.remove();
tdElementParent.find('td:eq(' + newPos + ')').before(tdElement);
});
// re-set an helper indexes
$table1Thead.find('th').each(function() {
var thElement = $(this);
thElement.data('columnIndex', $table1Thead.find('th').index(thElement));
});
}
});
});
</script>
</head>
<body>
<table id="table1">
<thead>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>

This JavaScript does drag-and-drop on columns. As it doesn't uses any framework you can combine it easily with any other framework.
Why do you nee a jQuery based solution when you can have one without the need of a specific framework.

Another approach to reorder columns with Jquery UI Sortable:
http://jsfiddle.net/pg7wH/
Needs
jQuery (tested with 1.7.2 - 2.0)
jQuery UI (tested with 1.8.18 - 1.10.2)
HTML:
<button id="getSorting">Get sorting</button><input id="showSorting" />
<table id="table1">
<thead class="ui-state-default"></thead>
<tbody></tbody>
</table>
JS:
$(function() {
var $table1 = $('#table1');
var $table1Thead = $table1.find('thead');
var $table1Tbody = $table1.find('tbody');
var startPos;
var oldPos;
// populate fake data
var maxCols = 10;
var maxRows = 50;
for (var i = 1; i <= maxCols; i++) {
$table1Thead.append('<th sort="' + i + '" id="column[' + i + ']">column ' + i + '</th>');
}
var rowHtml;
for (var x = 1; x <= maxRows; x++) {
rowHtml = '<tr>';
for (var i = 1; i <= maxCols; i++) {
//rowHtml += '<td>' + i + ' - ' + x + '</td>';
rowHtml += '<td>col ' + i + '</td>';
}
rowHtml += '</tr>';
$table1Tbody.append(rowHtml);
}
// Show sorting
$("button#getSorting").click(function() {
$('#showSorting').val($table1Thead.sortable('toArray', { attribute: "sort" } ))
console.log($table1Thead.sortable('toArray', { attribute: "sort" } ))
})
// The sorting
$table1Thead.sortable({
axis: "x" ,
items: 'th',
containment: 'parent',
cursor: 'move',
helper: 'clone',
distance: 5,
opacity: 0.5,
placeholder: 'ui-state-highlight',
start: function(event, ui) {
startPos = $table1Thead.find('th').index(ui.item);
oldPos = startPos;
},
change: function(event, ui) {
// Get position of the placeholder
var newPos = $table1Thead.find('th').index($table1Thead.find('th.ui-state-highlight'));
// If the position is right of the original position, substract it by one in cause of the hidden th
if(newPos>startPos)newPos--;
// move all the row elements
//console.log('Move: 'oldPos+' -> '+newPos);
$table1Tbody.find('tr').find('td:eq(' + oldPos + ')').each(function() {
var tdElement = $(this);
var tdElementParent = tdElement.parent();
if(newPos>oldPos)// Move it the right
tdElementParent.find('td:eq(' + newPos + ')').after(tdElement);
else// Move it the left
tdElementParent.find('td:eq(' + newPos + ')').before(tdElement);
});
oldPos = newPos;
}
});
});
Thanks to Nate Pinchot for his example.

Related

How to create loop to add eventListener for each item in a list

Wracking my brains on this one but I'm sure it's just my inexperience with js.
I have a list of items and I am trying to create an eventListener for each item row so when I mouseover the row some icons will appear. The icons should hide again on mouseout.
I am using setAttribute to change the opacity of the elements on mouseover and mouseout events.
My problem is after the loop runs to create the eventListeners the setAttribute only affects the very last row of the loop - regardless of which row I mouse over.
I have a JSFiddle here which shows you the exact behaviour (better than I can explain): https://jsfiddle.net/Finno/ds9q7zju/27/
Note: this is a simplified example but it exhibits the same behaviour. My real app has the items formatted in a drop down menu.
Here is the code :
var total = 8;
var items;
var row;
var sort;
var trash;
for (var i = 0; i < total; i++) {
items = items + '<div id="row' + i + '">';
items = items + '<span class="hidden" id="sort' + i + '">SORT</span>';
items = items + '<span id="content' + i + '">Some content</span>';
items = items + '<span class="hidden" id="trash' + i + '">TRASH</span>';
items = items + '</div><br>';
}
document.getElementById("queue").innerHTML = items;
for (var i = 0; i < total; i++) {
row = 'row' + i;
sort = 'sort' + i;
trash = 'trash' + i;
document.getElementById(row).addEventListener("mouseover", function() {
document.getElementById(sort).setAttribute("style", "opacity:1 !important");
document.getElementById(trash).setAttribute("style", "opacity:1 !important");
});
document.getElementById(row).addEventListener("mouseout", function() {
document.getElementById(sort).setAttribute("style", "opacity:0 !important");
document.getElementById(trash).setAttribute("style", "opacity:0 !important");
});
}
You need to recreate the variables in each iteration, Try this,
Also, you can use string interpolation in place of + to join strings
var total = 8;
var items;
for (var i = 0; i < total; i++) {
items = items + '<div id="row' + i + '">';
items = items + '<span class="hidden" id="sort' + i + '">SORT</span>';
items = items + '<span id="content' + i + '">Some content</span>';
items = items + '<span class="hidden" id="trash' + i + '">TRASH</span>';
items = items + '</div><br>';
}
document.getElementById("queue").innerHTML = items;
for (var i = 0; i < total; i++) {
let row = 'row' + i;
let sort = 'sort' + i;
let trash = 'trash' + i;
document.getElementById(row).addEventListener("mouseover", function() {
document.getElementById(sort).setAttribute("style", "opacity:1 !important");
document.getElementById(trash).setAttribute("style", "opacity:1 !important");
});
document.getElementById(row).addEventListener("mouseout", function() {
document.getElementById(sort).setAttribute("style", "opacity:0 !important");
document.getElementById(trash).setAttribute("style", "opacity:0 !important");
});
}

Select table cell as a group

In this table, I want to select multiple cells as a group.
You can select a target cell by clicking on it,
but I also want to click and drag to cover multiple cells as a group.
Is that possible to achieve that without any plugins (just use JQuery)?
This is what I want to achieve:
The array content will be:
["3-2", "3-3", "4-2", "4-3", "5-2", "5-3"]
Here is what I try so far:
var group = [];
var columnIndex = 7,
rowIndex = 10;
var $tableContainer = $('#tablecontainer'),
$table = $tableContainer.append('<table border="1" id="table1"></table>'),
$thead = $table.find('table').append('<thead></thead>'),
$tbody = $table.find('table').append('<tbody></tbody>');
var $columnNumber = "";
var $tdNumber = "";
for (var col = 1; col <= columnIndex; col++) {
$columnNumber += "<th>Column " + col + "</th>";
$tdNumber += "<td style='text-align: center; vertical-align: middle; color:red'></td>";
}
$thead = $thead.append('<tr><th>0</th>' + $columnNumber + '</tr>');
for (var row = 1; row <= rowIndex; row++) {
$tbody = $tbody.append('<tr><td>Row ' + row + '</td>' + $tdNumber + '</tr>');
}
$('#table1 > tbody > tr > td').hover(function() {
var colIndex = $(this).parent().children().index($(this));
var rowIndex = $(this).parent().parent().children().index($(this).parent());
$(this).attr("title", 'Row: ' + rowIndex + ', Column: ' + colIndex);
// console.log('Row: ' + rowIndex + ', Column: ' + colIndex);
});
$('#table1 > tbody > tr > td').click(function() {
var colIndex = $(this).parent().children().index($(this));
var rowIndex = $(this).parent().parent().children().index($(this).parent());
group.push(rowIndex + "-" + colIndex);
console.log(group);
$(this).css("background-color", "red");
// console.log('Row: ' + rowIndex + ', Column: ' + colIndex);
});
#table1>tbody>tr>td:hover {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="tablecontainer"></div>
Any help would be appreciated!
The functionality you want to achieve is possible by using jquery mouseover function.
I made a fiddle to get the desired output as you expect.
Fiddle
Hope this helps you in solving the issue.
-Help :)

Pure Js onclick element doesn't work

I'm having trouble when i run this code under greasemonkey the last position working and run function.
var arry = [];
arry = GM_listValues();
for ( var i = 0; i < arry.length; i++) {
document.getElementById('moje_menu').innerHTML = document.getElementById('moje_menu').innerHTML + '<p id="' + arry[i] + '">' + arry[i] + '</p>';
document.getElementById(arry[i]).onclick = delete;
}
On 10 position the last working ... WHY ????
When you replace the innerHTML you remove all previous event handlers.
In plain JS you can detect the click in the div but you need to check the event:
function removeP(p) {
console.log(p.id);
}
var arry = ["a","b","c"];
window.onload=function() {
for ( var i = 0; i < arry.length; i++) {
document.getElementById('moje_menu').innerHTML += '<p id="' + arry[i] + '">' + arry[i] + '</p>';
}
document.getElementById('moje_menu').onclick=function(e) {
var event = e?e:window.event,tgt = event.target || event.srcElement;
if (tgt.tagName.toLowerCase()=="p") {
console.log(tgt.id);
}
}
}
<div id="moje_menu"></div>
Alternative is inline since you generate the P anyway
var arry = [];
arry = GM_listValues();
for ( var i = 0; i < arry.length; i++) {
document.getElementById('moje_menu').innerHTML += '<p id="' + arry[i] + '" onclick="delete(this)">' + arry[i] + '</p>';
}
You can the modify delete (poor name for a function since delete is a built-in method) to handle the passed paragraph
Example:
function removeP(p) {
console.log(p.id);
}
var arry = ["a","b","c"];
for ( var i = 0; i < arry.length; i++) {
document.getElementById('moje_menu').innerHTML += '<p id="' + arry[i] + '" onclick="removeP(this)">' + arry[i] + '</p>';
}
<div id="moje_menu"></div>
In jQuery you can easily delegate:
function removeP() {
console.log(this.id);
}
$(function() {
var arry = ["a","b","c"];
var $menu = $('#moje_menu');
for (var i=0; i<arry.length; i++) {
$menu.append($('<p/>',{"id":arry[i], "text":arry[i]}))
}
$menu.on("click","p",removeP);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="moje_menu"></div>
This is my solution i dont like them but works.
var arry = [];
arry = GM_listValues();
for ( var i = 0; i<arry.length; i++) {
// if(arry[i].search('player')==''){
document.getElementById('moje_menu').innerHTML += '<p class="lista_farm" id="'+arry[i]+'">'+arry[i]+'</p>';
//document.getElementById(arry[i]).onclick = usun_farme;
//}
}
var lista_farm = document.getElementsByClassName('lista_farm');
for(var i = 0; i<lista_farm.length; i++){
lista_farm[i].onclick = usun_farme;
}

How to optimize jquery script (table creation N rows X 56 cols)

Hi I have a jquery scripts that takes table template and adds N rows (N=[1...100]) as clones of first TR. then each cell in each row is populated with some data (not all cells are always filled), each cell has " on clik " event attached, and on cell hover row, cell, coll is highlighted.
The problem i am facing is the optimization of generation (time) and usability (the mouse movemnts aren't smooth)
the code:
HTML template table:
<table id='schedulerview' class='myGrid'>
<colgroup id='col_0'></colgroup>
<colgroup id='col_1'></colgroup>
<colgroup id='col_2'></colgroup>
<colgroup id='col_3'></colgroup>
....
<colgroup id='col_55'></colgroup>
<thead>
<tr>
<th>0</th>
<th>1</th>
<th>2</th>
<th>3</th>
....
<th>51</th>
</tr>
</thead>
<tbody>
<tr id='template' style='display:none'>
<td id='0' HID='W0_Y_I' class='scheddata'>Week 1</td>
.....
<td id='51' HID='W55_Y_I' class='scheddata'>Week 52</td>
</tr>
</tbody>
</table>
CSS :
.litrow { background-color: #eee; }
.litcell { background-color: yellow; }
file codebehind.js
$(document).ready(function () {
//turn on row, cell, column highlight on hover
$("table#schedulerview tbody").on('mouseenter', 'tr', function () {
$(this).addClass('litrow');
});
$("table#schedulerview tbody").on('mouseleave', 'tr', function () {
$(this).removeClass('litrow');
});
$("table#schedulerview tbody").on('mouseenter', 'td', function () {
$(this).addClass('litcell');
$("colgroup").eq($(this).index()).addClass("litrow");
});
$("table#schedulerview tbody").on('mouseleave', 'td', function () {
$(this).removeClass('litcell');
$("colgroup").eq($(this).index()).removeClass("litrow");
});
//function for getting data and create schedule table from template table
getSchedule();
});
getschedule function:
function getSchedule() {
var data = "{userid:'" + userid + "',year:" + year + "}";
$.ajax({
type: "POST",
url: "/Scheduler.aspx/getSchedule",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (ret) {
var areas = JSON.parse(ret.d.Areas);
var schedule = JSON.parse(ret.d.Schedule);
//remove all rows from table that are not template
$('table#schedulerview tr.eventSchedule').remove();
//create row for each element from DB - prepare matrix elementsXWeeks
var $tr = $('#template');
$.each(areas, function (i, x) {
var $clone = $tr.clone();
$clone.css('display', 'block');
$clone.attr('id', 'new_row_' + i);
$clone.addClass('eventSchedule');
$clone.children('td:first').text(x.AreaName);
//for each cell in new row
$clone.children('td.scheddata').each(function () {
var $this = $(this);
var HID = $this.attr("HID").replace('_Y_', '_' + year + '_').replace('_I', '_' + x.IDObszaru);
$this.attr("HID", HID);
});
$tr.before($clone);
});
//fill in the matrix with scheduled data
$.each(schedule, function (i, x) {
$td = $("table#schedulerview td[HID='" + x.HID + "']");
$td.addClass(x.Status);
$td.attr("WeekNum", x.WeekNum);
$td.attr("PlanID", x.Id);
$td.parent().addClass('plannedrow');
});
},
error: function (ret) {
alert(ret.responseText);
}
});
}
The getSchedule() function lasts few seconds, is it possible to optimize it so it would be faster?
CHANGES:
I've tried different approach for row creation:
for (i = 0; i < areas.length; i++) {
$lasttr = $("table#schedulerview tbody").append("<tr id='new_row_" + i + "' class='eventSchedule' ></tr>");
$lasttr = $("table#schedulerview tbody tr#new_row_" + i);
for (j = 0; j < 56; j++) {
var sclass = "";
if (j == 0)
$lasttr.append("<td>" + areas[i].AreaName + "</td>");
if (j == 1)
$lasttr.append("<td>" + areas[i].AreaSubName + "</td>");
if (j == 2)
$lasttr.append("<td>" + areas[i].AreaParentName + "</td>");
if (j > 2) {
sclass = "'scheddata'";
k = j - 2;
$lasttr.append("<td class=" + sclass + " HID='W" + k + "_" + year + "_" + areas[i].AreaID + "'></td>");
}
}
}
but it's not fast enough- and the problem with hovering remains. (also when using css :hover pseudoclass.
Can you do something like this?
$(function () {
for (i = 0; i < 56; i++)
$("thead tr").append("<th>" + (i+1) +"</th>");
for (i = 0; i < 20; i++){
$("tbody").append("<tr />");
for (j = 0; j < 56; j++)
$("tbody tr:last-child").append("<td>" + ((i+1) + ": " + (j+1)) +"</td>");
}
});
table tr:hover td {background: #99f;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<thead><tr></tr></thead>
<tbody></tbody>
</table>

creating a html table in javascript

I want to create HTML table in java script. Inside a for loop I want to create a dynamic table which can be extended. This is how I am it using now:
function(json)
{
var content= $('#name1').html('').append('<td> Name: ' + json.name + '<td>');
var content= $('#address1').html('').append('<td> address: ' + json.address + '<td>');
var content= $('#age1').html('').append('<td> age: ' + json.age + '<td>');
var content= $('#status1').html('').append('<td> status: ' + json.status + '<td>');
}
HTML file is
<table>
<tr id="name1"></tr>
<tr id="address1"></tr>
<tr id="age1"></tr>
<tr id="status1"></tr>
</table>
now it is just with hardcore values but I want it auto generated and insert more rows if neccessary...
remove id from tr. Because if you need multiple row then id will be duplicated which is not valid.
<table id="mytable">
</table>
function(json)
{
for(i=0;i<json.length;i++){
var newRow= $("<tr></tr>");
newRow.append('<td> Name: ' + json[i].name + '<td>');
newRow.append('<td> address: ' + json[i].address + '<td>');
newRow.append('<td> age: ' + json[i].age + '<td>');
newRow.append('<td> status: ' + json[i].status + '<td>');
$("#mytable").append(newRow);
}
}
i think this will help you
function(json)
{
for(i=0;i<jsn.length;i++){
$('#YOUR_TABLE_ID').append("<tr><td>"+ json.name+"</td></tr>")
}
}
<table id="mytable">
<tr id="name1"><td></td></tr>
</table>
if (results != null && results.length > 0) {
// Build our table header
var content = "";
for(i=0;i<data.length;i++)
{
content += '<tr>';
content += '<td></td>'
}
content += '</tr>';
}
$("#mytable tbody").append(content);
}
You can Use Append Method to create Rows in a table like
for(i=0;i<data.length;i++)
{
$("YOUR_TABLE_ID").append("<tr><td>"+data[i]['name']+"</td><td>"+data[i]['address']+"</td><td>"+data[i]['age']+"</td><td>"+data[i]['status']+"</td></tr>");
}
I'm not clear with your requirement but i can provide you some basic code hope that helps you.
var jsonList = [{name:'Jhon',address:'Jhon Address goes here',age:'27',status:'Single'},
{name:'Smith',address:'Smith Address goes here' ,age:'32', status:'Single' }];
function createTable(){
var table = '<table>';
for(var ind=0;ind< jsonList.length;ind++)
table += fetchRowInformation(jsonList[ind]);
console.log(table+'</table>');
}
function fetchRowInformation(json){
return '<tr><td> Name: ' + json.name + '<td>'+'<td> address: ' + json.address + '<td>'+ '<td> age: ' + json.age + '<td>'+'<td> status: ' + json.status + '<td></tr>';
}
JS Fiddle Demo
function tableCreate(rows, columns) {
var body = document.body
tbl = document.createElement('table');
tbl.style.width = '20%';
tbl.style.border = '1px solid black';
for (var i = 0; i < rows; i++) {
var tr = tbl.insertRow();
for (var j = 0; j < columns; j++) {
var td = tr.insertCell();
td.appendChild(document.createTextNode('Cell'));
td.style.border = '1px solid black';
}
}
tbl.style.marginTop = '10px'
tbl.style.borderCollapse = 'collapse'
td.style.padding = '2px'
body.appendChild(tbl);
}
tableCreate(15, 10);

Categories