I have a table which is alphabetically ordered by name (using PHP mysql), now I would like to insert a new row at the correct position in the table without doing a new request to the server. Is there any way to go through the table checking every name and insert the new row at the correct position using jQuery/Javascript?
You could also insert it in the end (or anywhere), and then re-sort the entire table using js/jquery:
var table = $('table'),
rows = $('tr', table);
$('#sortIt').click(function () {
rows.sort(function(a, b) {
var keyA = $('td',a).text();
var keyB = $('td',b).text();
return (keyA > keyB) ? 1 : 0;
});
rows.each(function(index, row) {
table.append(row);
});
});
Example here at jsFiddle.
There are a lot of ways, this is just the one of them using jquery:
let's set your new name and new row el
var newName = 'YourNewName'
var newRow = $('<tr>') // created new row element with cells
get list of names, add newName and sort them; let's say your name column is 2
var names = $('td:nth-child(2)').map(function () {return $(this).text()})
names.push(newName)
var sorted = names.sort()
getting position of added name
var newNamePos = sorted.indexOf(newName)
inserting new row to found position
$('tr:nth-child(' + (newNamePos + 1) + ')').before(newRow)
Related
I'm working with a sheet that has around 700 rows, and each row has a phrase on the first Column.
I'm trying to write a script, that by given a sheet similar to the one I have - would add an additional column to the right with the number of words in this row and after adding the counting on each row, it will sort this sheet by descending order based on the added column.
What happens, is that apparently there's asynchronicity, it first sorts by the second column and only then adds the counting... I looked around and couldn't find a decent solution to this problem... any ideas?
The code:
function sortByNumOfKeywords(lang, col, sheet) {
var file = findFileByName("Translate Keywords List");
var spreadsheet = SpreadsheetApp.openById(file.getId());
//Getting the sheet name from the list above
var sheet = findSheetByName(spreadsheet,'Spanish');
//Getting Table bounds (Two-Dimensional array);
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
//add one column (Column H) to hold the number of words of each keyword in the first column
addWordsCounterCol(sheet, col, lastRow, lastColumn);
//sorting by the added column(H)
sheet.sort(8, false);
}
//sets a new column at the end of the table with the number of keywords of each cell in the given Row
function addWordsCounterCol(sheet, col, lastRow, lastCol){
sheet.activate();
var colChar = String.fromCharCode(65 + col-1); //Converts the Col number to it cohherent Big letter
var formulas = []; //Formulas will be set as a two-dimensional array
for(var i=2; i<lastRow+1; i++){
var cell = sheet.getRange("" +colChar + i);
var numOfKeys = "=COUNTA(SPLIT(trim("+ colChar + i + "), \" \"))";
formulas[i-2] = []; //initializing row with a new array
formulas[i-2].push(""+numOfKeys); // each row has only one column, with this specific String
}
var cells = sheet.getRange("H2:H"+(lastRow));
cells.setFormulas(formulas);
}
Try use flush(). Applies all pending Spreadsheet changes.
It works fine for me in your code:
...
SpreadsheetApp.flush();
//sorting by the added column(H)
sheet.sort(8, false);
...
I'm testing Datatables plugin and need some advice. My problem is that I can't delete a specific row in my table after ordering. For removing rows I use .index() method. Here is my fiddle
At first I find closest row:
var row = $(this).closest('tr');
then using this code to set index number:
var index = $("#example tbody").children().index(row);
And of course after ordering this index number changes.
Can you suggest something more efficient?
Considering name as unique entry:
var name = $(row).find('td:first').text();
for (var i = 0; i < dataSort.length; i++) {
if (dataSort[i][0] == name) {
break;
}
}
dataSort.splice(i, 1);
Fiddle here
this may be the code u needed...
var row = $(this).closest('tr');
var nRow = row[0];
dataTable.dataTable().fnDeleteRow(nRow);
I have a form/table set up that's cloning rows with specific valued names so that they can be processed separately once the form submits. All seems to be well unless you fill out information on the 5th row (the row being cloned) and then it copies all of the data over into the cloned row.
Is there an easy way to reset the values to NULL and 0 during the cloning process?
(I have two rows on bottom that are tallying/totalling each column, hence the tr:nth-last-child(2))
var totalRows = 5;
function addrow() {
totalRows++;
var clonedRow = $("table#maintable tr:nth-child(5)").clone(); //this will grab the 5th table row.
//get the textfield
var tfName = $("input.name",clonedRow);
var tfproA = $("input.proA",clonedRow);
var tfproB = $("input.proB",clonedRow);
var tfproC = $("input.proC",clonedRow);
var tfproD = $("input.proD",clonedRow);
var tfproE = $("input.proE",clonedRow);
var tfproF = $("input.proF",clonedRow);
var tfproG = $("input.proG",clonedRow);
var tfproH = $("input.proH",clonedRow);
var tfproI = $("input.proI",clonedRow);
var tfproJ = $("input.proJ",clonedRow);
var tfproK = $("input.proK",clonedRow);
var tfproL = $("input.proL",clonedRow);
var tfproM = $("input.proM",clonedRow);
var tfproN = $("input.proN",clonedRow);
//change their names
tfName.attr("name","name"+totalRows);
tfproA.attr("name","proA"+totalRows);
tfproB.attr("name","proB"+totalRows);
tfproC.attr("name","proC"+totalRows);
tfproD.attr("name","proD"+totalRows);
tfproE.attr("name","proE"+totalRows);
tfproF.attr("name","proF"+totalRows);
tfproG.attr("name","proG"+totalRows);
tfproH.attr("name","proH"+totalRows);
tfproI.attr("name","proI"+totalRows);
tfproJ.attr("name","proJ"+totalRows);
tfproK.attr("name","proK"+totalRows);
tfproL.attr("name","proL"+totalRows);
tfproM.attr("name","proM"+totalRows);
tfproN.attr("name","proN"+totalRows);
$("table#maintable tr:nth-last-child(2)").before(clonedRow); //add the row back to the table before the last 2nd to last row
console.log('done')
}
You can chain together a call to val()
tfName.attr("name","name"+totalRows).val(0) or
tfName.attr("name","name"+totalRows).val('')
I am attempting to send an array through the callback and having no luck. Let me explain my intent and perhaps an expert out there can send me some ideas for how to solve this dilema.
I have creates a spreadsheet that collects data. I then have a UI script which pulls row data into a flex table for a user to process by clicking a checkbox. I created a separate flex table that contains the checkboxes which the user checks or leaves blank. In my script I need to send an array that contains the checkbox condition. Why? Because I also need the row # or array placement that I can push to the spreadsheet to send the correct updated status for the data.
The script only pulls data that needs action into the UI. Thus I may be acting on Rows 1,3,4,5,and 8 of the spreadsheet but on the UI flextable the row that correspond to the data are rows 1,2,3,4,5 thus the row assignments don't match. BUT if I use an array I can capture that the row pulled was 1,3,4,5,and 8 and then update the spreadsheet accordingly.
However, that is the problem when I try to callback my array labeled offset[inc] I cannot get it to work I get run errors of cannot find method addcallback and cannot get it to work.
Recommendations on how to send an array through the addcallback method or alternate recommendations would be appreciated.
Thanks,
Sean Nutzman
function doGet(e){
var app = UiApp.createApplication();
//Create Caption Panel
var captionPanel = app.createCaptionPanel('Detention Attendance').setWidth('350px').setHeight('75px').setStyleAttribute('fontWeight', 'bold').setStyleAttribute('fontSize', '24px');
//Add a widget to caption panel
captionPanel.add(app.createLabel("Please enter attendance for Detention by clicking the checkbox next to the student's name if they were present. Then click Sumbit."));
//add the caption panel to the application
app.add(captionPanel);
var panel = app.createHorizontalPanel();
var flexTable = app.createFlexTable().setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2)
.setCellSpacing(50)
.setCellPadding(6);
//Get Data from spreadsheet
var spreadsheetId = '0Aup0nXQ4K-pydFREb1FFcTFYX3lOenNQenR1Q01jQ1E'; //Change this to the Spreadsheet ID
var dataArray = getData(spreadsheetId);
var inc = 1;
//Load data into table cells
for (var row = 0; row<dataArray.length; row++) {
var booleanCheck = dataArray[row] [17];
var offset = new Array();
if (booleanCheck == "" || booleanCheck == "Date Served") {
if (row > 0) {
Logger.log("Row value = " + row);
var ticketDate = dataArray[row] [0];
var dateStamp = Utilities.formatDate(new Date(ticketDate), "America/Chicago", "MM/dd/yyyy");
dataArray[row] [0] = dateStamp;
var ticketDate2 = dataArray[row] [16];
var dateStamp2 = Utilities.formatDate(new Date(ticketDate2), "America/Chicago", "MM/dd/yyyy");
dataArray[row] [16] = dateStamp2;
flexTable.setText(row, 1, dataArray[row][2].toString());
flexTable.setText(row, 0, dataArray[row][0].toString());
flexTable.setText(row, 2, dataArray[row][16].toString());
offset[inc] = row; inc++;
Logger.log('Inc variable = ' + inc);
Logger.log('Offset = ' + offset[inc-1]);
} else {
Logger.log("Inside ELSE row is not > 0");
Logger.log("Row value here = " + row);
flexTable.setText(0, 1, "Student's Name").setStyleAttribute(0, 1, 'fontWeight', 'bold');
flexTable.setText(0, 0, "Date Assigned").setStyleAttribute(0, 0, 'fontWeight', 'bold');
flexTable.setText(0, 2, "Date Delinquent").setStyleAttribute(0, 2, 'fontWeight', 'bold');
}
}
}
Logger.log(offset);
panel.add(flexTable);
var check1 = app.createCheckBox().setName('ch1');
var check2 = app.createCheckBox().setName('ch2');
var check3 = app.createCheckBox().setName('ch3');
var check4 = app.createCheckBox().setName('ch4');
var check5 = app.createCheckBox().setName('ch5');
var check6 = app.createCheckBox().setName('ch6');
var check7 = app.createCheckBox().setName('ch7');
var check8 = app.createCheckBox().setName('ch8');
var check9 = app.createCheckBox().setName('ch9');
var submitButton = app.createButton("Submit");
var handler = app.createServerClickHandler('updateStatus');
handler.addCallbackElement(check1)
.addCallbackElement(check2)
.addCallbackElement(check3)
.addCallbackElement(check4)
.addCallbackElement(check5)
.addCallbackElement(check6)
.addCallbackElement(check7)
.addCallbackElement(check8)
.addCallbackElement(check9)
.addCallbackElement(offset);
submitButton.addClickHandler(handler);
handler.addCallbackElement(check1)
.addCallbackElement(check2)
.addCallbackElement(check3)
.addCallbackElement(check4)
.addCallbackElement(check5)
.addCallbackElement(check6)
.addCallbackElement(check7)
.addCallbackElement(check8)
.addCallbackElement(check9)
.addCallbackElement(offset);
var table = app.createGrid(11,1).setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2)
.setWidth('75px')
.setCellSpacing(5)
.setCellPadding(6);
table.setStyleAttributes({textAlign: "center"});
table.setStyleAttribute('fontWeight', 'bold').setText(0, 0, 'Attendance');
table.setWidget(1,0, (check1));
table.setWidget(2,0, (check2));
table.setWidget(3,0, (check3));
table.setWidget(4,0, (check4));
table.setWidget(5,0, (check5));
table.setWidget(6,0, (check6));
table.setWidget(7,0, (check7));
table.setWidget(8,0, (check8));
table.setWidget(9,0, (check9));
table.setWidget(10,0,(submitButton));
panel.add(table);
app.add(panel);
app.close();
return app;
}
What I usually do is to convert the array to a string and write it on the widget's tag.
Then I can retrieve it using e.parameter.widgetName_tag in the handler function. At this point I can split it to get back the array : e.parameter.widgetName_tag.split(',');
You'll have to be careful when choosing the join and split character since your data might contain a comma (which is the default separator in arrays)... I often use a | or any other 'uncommon' character (Ë,Í;∆) in combination with join('∆') and split('∆') so I'm sure I get the array back as it should.
Of course the widget must be included in the callBackElement but this is easily achieved by using the highest level parent UiApp element as callBackElement.
Last comment : try to use widget Ids that will simplify your life ... for example use Ids containing a number that corresponds to the array index ( chk0, chk1, chk2...) so that you can easily retrieve the numeric value to use in your handler function using something like this :
Number(e.parameter.source.replace(/[a-z]/ig,''))
which will give you a number that identifies which checkBox is the origin of the handler call so you can write :
var arrayElement = e.parameter.widgetName_tag.split(',')[Number(e.parameter.source.replace(/[a-z]/ig,''))];
var array = ['foo','poo'];
var arrayString = JSON.stringify(array);
At that point, just attach arrayString to a callback element and voila! Then in the handlerFunction, you access it out with e.parameter.arrayString and then parse it to return it back to an array like so:
var array = JSON.parse(e.parameter.arrayName);
//array = ['foo','poo']
$('.myclass').attr('id');
myclass is the class of the selected table cells which have unique ids. No more than 2 table cells can be selected at once by the user. I need to capture the ids of the selected table cells and assign them to var1 and var2. Users can deselect cells and choose new ones... I thought about using an array but that's probably not the best way.
I'd go with the array option using map(), eg
var ids = $('.myclass').map(function() {
return this.id;
}).get();
if (ids.length >= 2) {
var var1 = ids[0];
var var2 = ids[1];
}
var selectedCells = [];
$('.myclass').each(function() { selectedCells.push($(this).attr('id')) });
Create an array and assign it to var1 and var 2 depending upon size.
arr = $.map($('.myclass'), function (element) {
return element.id;
});