Currently, I'm working on a project to pull data from a Google Form/Spreadsheet and have it appear on a website using JQuery/DataTables. I had received help on getting the data to appear on the site, but I've hit a new issue.
Previous Question: Is it possible to create a public database (spreadsheet) search with Google Scripts?
On Google, I have a form which outputs eight columns:
Timestamp
Title
Author
Type
URL
Topic(s)
Country(s)
Tages
Of these, I don't need the timestamp to appear, and I would like the title to link to the URL if the URL exists. Since I'm not quite fluent with Javascript or DataTables, I made a second sheet which I tried to simplified it down to the following six:
Title (currently being formatted as an <a> tag using the URL)
Author
Type
Topic(s)
Country(s)
Tages
This almost works, except that the script I'm using to construct the table renders the Title field as it is in the cell with the being visible in the table. See the table under the title "Actual Output" for the current situation; the table under "Target Table Appearance" is what I'm aiming for.
Current Output: http://interculturalresources.weebly.com/webtest.html
Table Creation Script: http://www.weebly.com/uploads/1/7/5/3/17534471/tablescript.js
Thus, is there a way to have the be given as a link despite being put together in a Google Spreadsheet cell? Alternatively, is there a way to edit the current script to a) ignore the timestamp column and b) make the Title output a link to the URL from the URL column (with proper conditionals)?
EDIT: I'm focusing on the links now; I have a solution for the timestamp which involves copying the data to a new spreadsheet (since forms are strict with copy/pasting information). The current issue is getting each entry to have a link assuming the URL is in the first column, and the Title is in the second column. Please read Mogsdad's answer and my first comment for more information.
Solution: First, my thanks to Mogsdad for the "spark" of inspiration and insight which led me in the correct direction towards the solution. To explain the general idea, I wanted to not display one column (URL) from a Google Spreadsheet on the target website, yet use it's content to create a link in another (Title). Then, once the table was made, DataTables is used to format it. All cells in the table must contain something, so if the cell is to be blank, it must be filled with "None".
function cellEntries(json, dest, divId) {
var table = document.createElement('table');
table.setAttribute("id", divId + "table"); //Assign ID to <table> from the <div> name.
var thead = document.createElement('thead');
var tbody = document.createElement('tbody');
var thr;
var tr;
var entries = json.feed.entry;
var cols = json.feed.gs$colCount.$t; //The number of columns in the sheet.
var link; //Teporary holder for the URL of a row.
for (var i=0; i <cols; i++) { //For the first row of cells (column titles),
var entry = json.feed.entry[i];
if (entry.gs$cell.col == '1') { //For First Column / URL Column, (1)
if (thr != null) {
tbody.appendChild(thr);
}
thr = document.createElement('tr'); //Create <thr>/<tr> (???).
}
else { //For all other columns,
var th = document.createElement('th');
th.appendChild(document.createTextNode(entry.content.$t)); //Create title for each column.
thr.appendChild(th);
}
}
for (var i=cols; i < json.feed.entry.length; i++) { //For all remaining cells,
var entry = json.feed.entry[i];
if (entry.gs$cell.col == '1') { //For First Column / URL Column, (1)
if (tr != null) {
tbody.appendChild(tr);
}
tr = document.createElement('tr'); //Create <tr>.
hlink = entry.content.$t; //Put URL content into hlink.
}
else if (entry.gs$cell.col == '2') { //For Title Column,(2)
var td = document.createElement('td');
if (hlink != "None") { //If there is a link,
var alink = document.createElement('a'); //Make <a>
alink.appendChild(document.createTextNode(entry.content.$t)); //Put content in <a>
alink.setAttribute('href',hlink); //Assign URL to <a>.
td.appendChild(alink); //Put <a> in <td>.
}
else { //If there is no link,
td.appendChild(document.createTextNode(entry.content.$t)); //Put content in <td>.
}
tr.appendChild(td);
}
else { //For all other columns,
var td = document.createElement('td');
if (entry.content.$t != "None") { //If content is not "None",
td.appendChild(document.createTextNode(entry.content.$t)); //Output the content.
}
else { //Else,
td.appendChild(document.createTextNode("")); //Output a blank cell.
}
tr.appendChild(td);
}
}
$(thead).append(thr);
$(tbody).append(tr);
$(table).append(thead);
$(table).append(tbody);
$(dest).append(table);
$(dest + "table").dataTable();
};
function importGSS(json){
var divId = "targetdivid" //ID of the target <div>.
cellEntries(json, "#" + divId, divId);
};
Around this bit in tablescript.js:
var th = document.createElement('th');
th.appendChild(document.createTextNode(entry.content.$t));
>>>>
thr.appendChild(th)
You can add a hyperlink by doing this:
th.setAttribute('href',<link>);
...with <link> set to the hyperlink for the particular publication.
To make this work, you could rework your spreadsheet source to have the link in one column, and the Title in another. Then modify tablescript.js to combine the link and text, something like this:
var hlink = null; // Temporary storage for hyperlink
for (var i=0; i <cols; i++) {
var entry = json.feed.entry[i];
if (entry.gs$cell.col == '1') {
if (thr != null) {
tbody.appendChild(thr);
}
thr = document.createElement('tr');
}
// Element 0 assumed to have hyperlink
if (i == 0) {
hlink = entry.content.$t;
}
else {
var th = document.createElement('th');
// If we have an hlink, set the href attribute.
if (hlink !== null) {
th.setAttribute('href',hlink);
hlink = null;
}
th.appendChild(document.createTextNode(entry.content.$t));
thr.appendChild(th);
}
}
Related
I've tried with a stupid way of inserting code for a new table, but not even that seems to work. What would be the proper way?
Here's what I tried to do:
var table = document.getElementsByClassName("test")
[0].getElementsByClassName("tableclass");
for (var i = 0, l = table.length; i < l; i++) {
var content = table[i];
let s = content.innerHTML;
s = s.replace(/table/g, 'table border="1"');
s = s.replace(/tr>[\s\S]*?<tr>[\s\S]*?<td>3/g, 'tr>\r\n<tr>\r\n<td>3');
content.innerHTML = s;
}
And a fiddle: https://jsfiddle.net/d10tk7nr/1/
Also, the reason my stupid way doesn't contain the whole table is because some of the cells where I want to eventually use this would contain random data and I don't know how to skip that.
If you want to create a new HTML-Element, every browser got you covered on that.
var tr = document.createElement('tr');
console.log(tr);
The browser console will show you exactly what you have created - a new HTML element that is not yet part of the DOM:
<tr></tr>
The same goes with the creation of some content for that table row:
var td1 = document.createElement('td'),
td2 = document.createElement('td');
td1.innerText = '5';
td2.innerText = '6';
console.log(td1, td2);
The result will be two td-elements:
<td>5</td> <td>6</td>
Now we have to glue these parts together. Browsers will also have you coverd on this:
tr.append(td1);
tr.append(td2);
console.log(tr);
The result is a complete table row:
<tr><td>5</td><td>6</td></tr>
All we have to do is append this row to your table:
var table = document.querySelector('.test table tbody');
table.append(tr);
The elements you have created are now part of the DOM - child elements of the body of your table to be excact.
Click here for a fiddle
Edit
If you want to insert the new row to a specific place, you have to find the element you that should be next to it and use insertBefore. This would change the the last piece of code to:
var targetTr = document.querySelector('.test table tr:nth-child(2)');
targetTr.parentNode.insertBefore(tr, targetTr);
If you want to choose where to put your new row within your javascript, you can use the childNodes property:
console.log(table.childNodes);
I'd use insertAdjacentHTML, like so:
table[i].insertAdjacentHTML('beforeend', '<tr><td>5</td><td>6</td></tr>');
Please see this fiddle: https://jsfiddle.net/52axLsfn/4/
Also demonstrates how to set the border. Note that this code targets all tables, so depending on your situation you may want to be more specific.
LOOK at the image PLEASE
There is a table that is refreshing every second with AJAX. 2nd column of table has 0 or 1 inside. I want to replace 0 with one image and 1 with another image. Currently I am looping through all the rows but only last row of one kindof image is filled in. All row shoul have a picture in them. What am I doing wrong?
var warningImg = document.createElement("IMG");
warningImg.src = "icone/ic_warning.png";
var okImg = document.createElement("IMG");
okImg.src = "icone/ic_done.png";
$(document).ready(function(){
$.ajaxSetup({ cache: false });
setInterval(function() {
$.get("IOdoc.htm", function(result){
var stringArray = result.trim().split(",");
$('#safety tr:eq(0) td:eq(1)').text(stringArray[0]);
$('#safety tr:eq(1) td:eq(1)').text(stringArray[1]);
$('#safety tr:eq(2) td:eq(1)').text(stringArray[2]);
var safetyEls = document.querySelectorAll("#safety tr td:nth-child(2)");
for(var i=0; i < safetyEls.length ; i++){
if (safetyEls[i].innerHTML.trim() == "1")
{
safetyEls[i].appendChild(okImg);
}
else{
safetyEls[i].appendChild(warningImg);}
}
});
},1000);
});
I tried something that proves that for loop is working. I replaced appendChild with textContent just wrote some text.
safetyEls[i].textContent = "Warning"
This worked. Working table just with text
Each time you call the appendChild, you move the image you have created.
Try cloning it to create new image for each row:
if (safetyEls[i].innerHTML.trim() == "1")
{
safetyEls[i].appendChild(okImg.cloneNode(true));
}
else{
safetyEls[i].appendChild(warningImg.cloneNode(true));}
}
For more details see http://www.w3schools.com/jsref/met_node_clonenode.asp
I apologize in advance, English is not my native language.
I am working on a project that was delegated to me. I am working on a webpage, that is being generated by an XSLT file. I only have access to the source code of the generated page.
What does it do: The page shows a synopsis in form of a table. The left most column (lets call that one A) and the top most row (lets call it B) are the Header (?) segments (like in this table i found on google)
There are also Buttons in the top most row to sort the table.
Now the problem: There is a button to invert the table which activates the following code. This is where the problem is
I have this java code
// FAULTY FUNCTION BEGINNING
function swap_table_horizontally_vertically() {
//This is the code I already have
// Deletes all sort buttons
for (i = 0; i <= 1000; i++) {
try {
var sort_buttons = document.getElementById('sort_buttons');
}
catch(err) {
alert(err.message);
continue;
} finally {
sort_buttons.parentNode.removeChild(sort_buttons);
}
}
//End of the Code I made
//This code was already in the file
var old_table = document.getElementById('synopsis_table'),
old_table_rows = old_table.getElementsByTagName('tr'),
cols = old_table_rows.length, rows = old_table_rows[0].getElementsByTagName('td').length,
cell, next, temp_row, i = 0, new_table = document.createElement('table');
while(i < rows) {
cell = 0;
temp_row = document.createElement('tr');
if (i == 0) {
while(cell < cols) {
next = old_table_rows[cell++].getElementsByTagName('td')[0];
temp_row.appendChild(next);
}
new_table.appendChild(temp_row);
++i;
}
else {
while(cell < cols) {
next = old_table_rows[cell++].getElementsByTagName('td')[0];
temp_row.appendChild(next);
}
new_table.appendChild(temp_row);
++i;
}
}
old_table.parentNode.replaceChild(new_table, old_table);
new_table.setAttribute("id", "synopsis_table");
}
// FAULTY FUNCTION END
Now what I need is a way to add the buttons again into the new table head (top most row) with a class and id attribute.
To summarize: I need to delete the buttons from the previous top most row (because the left column shouldn't have them) and add them again to the new top most row (the previous left column).
I am using the following code to make a html table editable (this code is obtained from an online tutorial link: http://mrbool.com/how-to-create-an-editable-html-table-with-jquery/27425).
$("td").dblclick(function () {
//Obtain and record the value in the cell being edited. This value will be used later
var OriginalContent = $(this).text();
//Addition of class cellEditing the cell in which the user has double-clicked
$(this).addClass("cellEditing");
//Inserting an input in the cell containing the value that was originally on this.
$(this).html("<input type='text' value='" + OriginalContent + "' />");
//directing the focus (cursor) to the input that was just created, so that the user does not need to click on it again.
$(this).children().first().focus();
//the opening and closing function that handles the keypress event of the input.
//A reserved word this refers to the cell that was clicked.
//We use the functions first and children to get the first child element of the cell, ie the input.
$(this).children().first().keypress(function (e) {
//check if the pressed key is the Enter key
if (e.which == 13) {
var newContent = $(this).val();
$(this).parent().text(newContent);
$(this).parent().removeClass("cellEditing");
}
});
$(this).children().first().blur(function(){
$(this).parent().text(OriginalContent);
$(this).parent().removeClass("cellEditing");
});
});
It seems to work fine. Then I am using the following function to read the contents of the table and create a json representation:
function showRefTable(){
var headers = [];
var objects = [];
var headerRow = $('#dataTable thead tr');
var rows = $('#dataTable tbody tr');
headerRow.find('th').each(function(){
headers.push($(this).text());
});
for (var i=0; i<rows.length; i++){
var row = rows.eq(i);
var object = new Object();
for (var j=0; j<row.find('td').length; j++){
object[headers[j]] = row.find('td').eq(j).text();
}
objects.push(object);
}
var json = JSON.stringify(objects);
alert(json);
}
This function is used as a callback to an onclick event.
The problem is that the function used to read the table contents shows the original contents even if I make an edit (show page source shows the original content).
Thanks
It's really bad to read table contents from .text(). You will not be able to use any formatting for numbers and many other problems. You'd better of keeping table contents in standalone datasourse object and redrawing table from it every time when user changes values.
I would advise using kendo grid - it's powerfull, reliable js table.
EDIT: your function does not work, becuse you said you call it as callback to onclick event. So you read contents of the table before they actually changed.
You should read contents when they are saved. In your case, try calling you function when user saves the input (presses Enter)
if (e.which == 13) {
var newContent = $(this).val();
$(this).parent().text(newContent);
$(this).parent().removeClass("cellEditing");
//Now, when content is changed, call your function
showRefTable();
}
I have the following code:
$(document).ready(function() {
var id = 'cbx';
var idPrefix = 'Arrow';
var html = '<img .../>';
// query parent row
var rowq = $('#' + id);
if (rowq.length < 1) {
rowq = $('.' + id);
VersionHeader = true;
}
if (rowq[0]) {
rowq.addClass('ArrowHeader');
// set to 0 for header
var index = 0;
var row = rowq.parents('.g')[0].insertRow(index);
// assign id for new row
row.id = idPrefix + id;
// assign classes for style and tree
row.className = 'srcrow' + id;
// insert new cell
var cell = row.insertCell(0);
// assign html result
cell.innerHTML = html;
// set colspan
cell.colSpan = 1;
Now my problem is it adds the cell but it adds it under the first column. Is there a way to move through the columns? Granted I'm not an html expert at all. Just a beginner trying to get some stuff to work and would appreciate some help since I'm totally lost. I didn't include the html just ... through it.
Thanks
I'm not sure I'm understanding your question entirely correctly (I gather you are attempting to insert a cell into a new row, and you want to select into which column it is inserted?). Assuming that's what you meant:
row.insertCell(0)
This is your problem. The insertCell method takes as an argument the index of the column into which the cell should be inserted. Index 0 is the first column, index 1 is the second column, and so on. So try replacing the 0 with the appropriate index.