I have an html table with 14 columns and 11 rows. Each td element has a specific id associated with it that correlates to the column and row. For example the 3rd column and 2nd row would be <td id="3-2"></td>. I'm querying a database that has information which goes into each td based on what day the user chooses on a datepicker. If that data meets a certain criteria, I set the rowspan attribute on my td element to "2". The problem is when I do that a <td> gets pushed to the outside of the table. Here is my js so you can get an idea of what I'm doing. The most important part of this starts at the for loop
function createAppointments() {
//clear the dom with the clearTags() function so appointments don't overlap
clearTags();
//get all of the appointments that are related to the current day. Create a date variable equal to the datepicker value
let myDate = document.getElementById('myDate');
let day = myDate.value;
console.log(day);
//update the h1 element to display the current date
document.getElementById('date').innerText = day;
//use day in a doquery to query appts where fid 14(appointment date) is equal to the datepicker value
let appts = qdb.DoQueryWithQueryString(apptsDBID,"{'14'.'EX'.'"+ day + "'}","3.6.18.17.11.37.39.41.42.43.44")//6-appt time/18-service/17-patient/11-trainer/37-element id/39-duration number/41-hex code/42 - notes/43 - top/ 44- left
let records = qdb.selectNodes(appts,"*/table/records/record");
//now we have our xml tree of all of our appointment records
//loop through each record. The element id is a field in quickbase(37) which automatically takes the trainer name and appends a "-" and the start time of the appointment, which corresponds with the td ids.
for(var i=0;i<records.length;i++) {
debugger;
let rec = records[i];
let patient = gf(rec,17);
let service = gf(rec,18);
let notes = gf(rec,42);
let textToDisplay = `${patient}-${service}`;
let eid = gf(rec,37);
let rid = gf(rec,3);
let rspan = gf(rec,39);
let t = gf(rec,43); //top px
let l = gf(rec, 44);//left percentage
console.log(`top is ${t} and left is ${l}`);
let p = document.createElement("p");//create a new paragraph element to put in the table data
let q = document.getElementById(eid);
q.appendChild(p);//append the created paragraph element to the td for the onmouseover event
p.innerText = textToDisplay;
p.setAttribute("id",rid);
p.setAttribute("data-toppx",t);
p.setAttribute("data-leftpercent",l);
p.setAttribute("data-notes", notes);
q.style.backgroundColor = gf(rec,41);
q.style.borderRadius = "10px";
q.style.width = "225px";
p.style.fontWeight = "bold";
q.style.paddingLeft = "15px";
p.setAttribute("onmouseover","showNotes(this)");//set the show notes function as an attribute of the paragraph
p.setAttribute("onmouseleave","hideNotes()");//hide the notes div when not hovered
q.setAttribute("rowspan",gf(rec,39));}//set the row span attribute based on the rspan field in quick base
}
function showNotes(obj) {
let contents = obj.dataset.notes;
let topPX = obj.dataset.toppx;
let leftP = obj.dataset.leftpercent;
console.log(obj);
let notes = document.querySelector('#notes');
notes.style.visibility = "visible";
notes.innerHTML = contents;
console.log(topPX);
console.log(leftP);
notes.style.top = topPX;
notes.style.left = leftP;
}
function hideNotes() {
let notes = document.querySelector('#notes');
notes.style.visibility = "hidden";
}
How can I prevent <td>s from being pushed outside my table? FYI the table is built statically not dynamically.
Try adding some css to your table like setting the table-layout to fixed and for td
word-wrap to break-word
Something like this
td { word-wrap: break-word; } table { table-layout: fixed; width: 100%; }
Related
I am trying to add missing cells in angular material calendar.
Below is my html
<mat-calendar
[dateClass]="dateClass()"
[startAt]="month"
[selected]="selectedDate"
(selectedChange)="onSelect($event)">
</mat-calendar>
I used ViewChildern to access its dom
#ViewChildren(MatCalendar, { read: ElementRef }) calendars: QueryList<ElementRef>;
I was able to add empty extra row to the bottom of angular material calendar
this.calendars.forEach(calendarEl => {
const tbody: HTMLElement = calendarEl.nativeElement.querySelector('tbody');
//ToDO:-- identify last row, count number of cells in last row,if its less than 7 add missing cells
//Added extra row to the bottom
const tr = (document.createElement('tr') as HTMLTableRowElement);
tr.className = 'date-class';
for (let i = 0; i < 7; i++) {
tr.appendChild(document.createElement('td'));
}
tbody.appendChild(tr);
});
Here is the image of calendar I have without adding missing cells(td). Needed to add 4 more cells
Can we do something like getting the last row and add append number of <td> to that row so that total count of <td> children become 7.
let lastRow = calendarEl.nativeElement.querySelector('tbody tr:last-child');
let vaccantColCount = 7 - lastRow.querySelectorAll('td').length;
console.log(vaccantColCount);
while(vaccantColCount > 0) {
lastRow.appendChild(document.createElement('td'));
vaccantColCount--;
}
I have a table, and each row is added through JavaScript. I create these rows so that when they're clicked another cell will be created beneath them where I can display additional information. Now I want to be able to destroy the row I just created when the user clicks a button etc. So essentially, I need to be able to have the row I created have an onclick attribute, but it doesn't seem to work... I've tried everything I can think of so any help would be awesome!
var table = document.getElementById("main_table");
var row = table.insertRow(1);
row.id = count;
row.onclick = function ()
{
var id = this.id;
var target = document.getElementById(id);
var newElement = document.createElement('tr');
newElement.style.height = "500px";
newElement.id = id + "" + id;
//newElement.innerHTML = text;
target.parentNode.insertBefore(newElement, target.nextSibling );
//var newRow = document.createElement("tr");
//var list = document.getElementById(id);
//list.insertAfter(newRow,list);
var newRow = table.insertRow(newID);
}
I have tried to mimic your problem with below fiddle.
http://jsfiddle.net/kr7ttdhq/12/
newElement.onclick = createClickableCells;
del.onclick = delCell;
The above code shows the snippet from the fiddle
During the onclick event of the cell. New cells are created which in turn have the same onclick events as the first cell.
Moreover, a 'close' text cell is inserted by which you can delete the entire row.
Hope this helps
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);
}
}
Firstly,
If possible, I would like to do this without JQuery, and purely Javascript.
Ok so I have an html table with rows getting added dynamically to it.
In each row is a:
Select Element (id = "ddFields")
Text Input Element (id = "tfValue")
Button Element (no id)
The Button Element removes the row for which it is situated
The Select Element has a default option of "" and then other 'valid' options
The Text Input is added to the row but it is hidden.
All elements are in the same
Basically I would like for the Select Element to show the hidden text input element if the selected index is != 0
so far I have this for my onchange function:
function itemChanged(dropdown) //called from itemChanged(this)
{
var cell = dropdown.parentNode;
var row = cell.parentNode;
var rowIndex = dropdown.parentNode.parentNode.rowIndex;
var index = dropdown.selectedIndex;
var option = dropdown.options[dropdown.selectedIndex].text;
if(index >0)
{
alert(row);
var obj=row.getElementById("tfValue"); //tfValue is the Text Field element
alert(obj);
//row.getElementById("tfValue").hidden = "false"; //doesn't work
//row.getElementById("tfValue").setAttribute("hidden","true"); //doesn't work
}
else
{
alert('none selected');
}
}
Finally figured it out. So here it is:
SCENARIO:
A table that has rows added to it dynamically.
In each row there is a select element and an input text element.
The select element changes text-value of the input text element based on the index of the select element.
in your select element set the onchange function to this:
onchange="selectionChanged(this)"
then create a javascript function shown below:
function selectionChanged(dropdown)
{
//get the currently selected index of the dropdown
var index = dropdown.selectedIndex;
//get the cell in which your dropdown is
var cell = dropdown.parentNode;located
//get the row of that cell
var row = cell.parentNode;
//get the array of all cells in that row
var cells = row.getElementsByTagName("td");
//my text-field is in the second cell
//get the first input element in the second cell
var textfield = cells[1].getElementsByTagName("input")[0];
//i use the first option of the dropdown as a default option with no value
if(index > 0)
{
textfield.value = "anything-you-want";
}
else
{
textfield.value = null;
}
}
Hope this helps whoever. It bugged me for a very long time. Thanks shub for the help! :)
first, I hope you are not repeating your ids. No two items should have the same id.
If you're iterating, create id1, id2, id3.
Also, this is not necessary but I suggest introducing your vars like this:
var a = x,
b = y,
c = z;
If you decide to use jQuery you could just do this:
$('#tableid').on('click','button',function(){
$(this).parent().parent().remove();
});
$('#tableid').on('change', 'select',function(){
if($(this).val()){ $(this).next().show(); }
});
Be sure to change #tableid to match your table's id.
This assumes the text input is the very next element after the select box. If not so, adjust as necessary or ask and I'll edit.
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.