I am using JavaScript to insert elements inside a container div:
<tr>
<td align="left">
</td>
<td style="background-color:#5D7B9D">
<div id="headerMasterDiv">
</div>
</td>
<td style="width: 18px; height: 18px;">
</td>
</tr>
for (var i=0; i < len; i++ )
{
id = "headerColumn_" + i.toString();
width = columnWidths[i];
text = columnTexts[i];
html = " <div id=\""+id+"\" class=\"test\">"+text+"</div> ";
header.innerHTML += html;
}
However I would like the inner to overflow, so I can activate an horizontal scrollbar. But instead they are wrapping:
Tx.
Just add the overflow:auto to your div.
In the test class :
.test
{
overflow:auto;
}
Or inline style, i suggest using quot and double quot it's more readable :
' <div id="'+id+'" class="test" style="overflow:auto">'+text+'</div> ';
Related
I have this JSON from which I need to create a table. This table must be a legend for a webmap created with OpenLayers 6. As you have seen the JSON comes from Geoserver.
Below my code:
let updateLegend = function(resolution) {
let graphicUrl = strutturale_puc.getSource().getLegendUrl(
resolution,
{'FORMAT': 'application/json'}
);
if(graphicUrl) {
fetch(graphicUrl)
.then(function (response) {
return response.text();
})
.then(function (data) {
const jsonData = JSON.parse(data);
const legendData = jsonData.Legend[0].rules;
const table = document.getElementById("table");
const footer = table.createTFoot();
legendData.forEach((value) => {
cellStroke = value.symbolizers[0].Polygon.stroke;
cellFill = value.symbolizers[0].Polygon.fill;
cellContent = value.name;
const tableRaw = footer.insertRow(value);
tableRaw.insertCell(0).innerHTML = '<td style="border: 4px solid ' + cellStroke + '; background-color: ' + cellFill + '; max-width: 10px;"></td>';
tableRaw.insertCell(1).innerHTML = '<td style="border: none;">' + cellContent + '</td>';
console.log(tableRaw);
});
}).catch((error) => {
console.error(error)
});
}
The table is inside a div:
<div class="" id="legend">
<table class="table" id="table">
</table>
</div>
My problem is that I can't see any style when the table is created, I can see only the text(cellContent). For me is strange because if I use this:
<div class="">
<table>
<tr>
<td style="border: 4px solid #791919; background-color: #A71C1C; max-width: 10px;"></td>
<td style="border: none;">Item</td>
</tr>
</table>
</div>
I can see all correctly. What I wrong?
.insertCell creates a <td> element, inserts it into the table, and returns a reference to it (per the spec).
You then set the contents of that <td> to contain another <td> where you add the styling rule.
So now you essentially have:
<td>
<td style="border: 4px solid #791919; background-color: #A71C1C; max-width: 10px;"></td>
</td>
You can only have a <td> tag within a <tr> tag, so the browser removes the internal <td> tag (along with its styling), and adds its contents to the original <td>.
To solve the issue, you need to add the styling to the <td> that it makes for you. For example:
let firstCell = tableRaw.insertCell(0);
firstCell.setAttribute("style", 'border: 4px solid ' + cellStroke + '; background-color: ' + cellFill + '; max-width: 10px;');
firstCell.innerHTML = "";
Code quality notes:
You should use CSS classes rather that inline styles.
You should use template literals rather than inline string concatenation.
I have a table on one side and an area for an image on the right.
When a row within the table is hovered over, I want a different image to display.
There will end up being 20 rows of data, with 20 respective images.
I have javascript:
document.getElementById("showlot1").mouseover = function() {
document.getElementById("lot1").style.visibility = "visible"; }
document.getElementById("showlot2").mouseover = function() {
document.getElementById("lot2").style.visibility = "visible"; }
CSS:
#lot1, #lot2 { visibility: hidden; }
HTML Table:
<table style="width: 100%;" cellpadding="2">
<tbody>
<tr class="hover">
<td style="text-align: center;">
<a id="showlot1">1</a>
</td>
<td style="text-align: center;">
<a id="showlot1">3.4ha (8.4 acres)</a>
</td>
<td style="text-align: center;">
<a id="showlot1"></a>$99,000</a>
</td>
</tr>
<tr class="hover">
<td style="text-align: center;">
<a id="showlot2">2</a>
</td>
<td style="text-align: center;">
<a id="showlot2">3.5ha (8.6 acres)</a>
</td>
<td style="text-align: center;">
<a id="showlot2">$99,000</a>
</td>
</tr>
</tbody>
</table>
HTML Image Placer:
<img id="lot1" src="/wp-content/uploads/sites/291/2015/02/QA-CONTOUR-LOT1.jpg" />
<img id="lot2" src="/wp-content/uploads/sites/291/2015/02/QA-CONTOUR-LOT2.jpg" />
One simple way would be to do it with css.
HTML
<img id="myimg" src="first_image"/>
CSS
#myimg:hover {
content: url('second_image');
}
See running JSFiddle example here
I found using classes to denote functional elements easier; a bunch of elements with ids (which is illegal by the way, as id's should be unique in the document) I changed to putting a class .showImage on your tr's and targeting them with event listeners.
I used CSS to set images to display:none; by default. This is more ideal than visibility:hidden because they disappear completely and won't take up space.
Instead of using anonymous functions, I split the desired result into two mouseover and mouseout handlers that toggle the display property. You'll see they also take a parameter index, which I used to determine which #lot to target:
function showImageOnMouseover(i) {<change display property to block>}
and
function hideImageOnMouseout(i) {<change display property to none>}
Where i is a variable used to find the right image using your convention #lot<i>
// get elements by class name
var elementSelection = document.getElementsByClassName('showImage');
// attach event listener to each element
for( var i=0; i<elementSelection.length; i++ ) {
elementSelection[i].addEventListener( 'mouseover', showImageOnMouseover(i+1) );
// pass i+1 to index since i starts out as 0. You could just as easily change the for loop to var i=1, or alter your #lot naming convention to start at 0.
elementSelection[i].addEventListener( 'mouseout', hideImageOnMouseout(i+1) );
}
// handle mouseover
function showImageOnMouseover( index ) {
return function(e) {
var imgId = 'lot' + index.toString();
console.log(imgId);
document.getElementById( imgId ).style = ( 'display: block' );
}
}
// handle mouseout
function hideImageOnMouseout( index ) {
return function(e) {
var imgId = 'lot' + index.toString();
document.getElementById( imgId ).style = ( 'display: none' );
}
}
#lot1 {
display: none;
}
#lot2 {
display: none;
}
<table cellpadding="2" style="width: 100%;">
<tbody>
<tr class="hover showImage">
<td style="text-align: center;">
<a>1</a>
</td>
<td style="text-align: center;">
<a>3.4ha (8.4 acres)</a>
</td>
<td style="text-align: center;">
<a></a>$99,000
</td>
</tr>
<tr class="hover showImage">
<td style="text-align: center;">
<a>2</a>
</td>
<td style="text-align: center;">
<a>3.5ha (8.6 acres)</a>
</td>
<td style="text-align: center;">
<a>$99,000</a>
</td>
</tr>
</tbody>
</table>
<img id="lot1" src="http://www.kaybojesen.com/wp-content/uploads/2013/07/505-Dessertske-ni-tre.png" />
<img id="lot2" src="https://www.house.com.au/images/hires/HAG-CU249610.jpg" />
guys, would be very grateful for advice I'm trying to implement Angular Material's Virtual Repeat with a custom directive for the list items, and I'm having issues binding directive functions md-repeat elements.
I want to apply scrolling function for fixed table header for each md-virtual element (I have like 20-30 tables)
<section class="container-fluid" ng-cloak style="background: #ffffff;" >
<md-virtual-repeat-container id="horizontal-container" style="height:830px;" >
<div md-item-size="430" my-post-repeat-directive md-virtual-repeat="group in tasks.content" ng-cloak>
<div class="wrap" style="margin-bottom: 15px;" id="table_{{group.id}}" >
<table class="table table-bordered table-striped" ng-cloak>
<thead >
<tr>
<th ng-repeat="name in tasks.headers.agents track by $index" ng-bind="name.title" ng-show="name.visible"></th>
</tr>
</thead>
<tbody >
<tr style="height:54px" ng-repeat="agent in tasks.content[$index].agents track by $index" ng-click="showMenu($event, navigation)">
<td ng-bind="agent.agt_id" style="font-weight:normal"></td>
<td ng-bind="agent.agt_presence" style="font-weight:normal"></td>
<td ng-bind="agent.agt_call_direction" style="font-weight:normal"></td>
<td ng-bind="agent.agt_calls_total" style="font-weight:normal"></td>
<td ng-bind="agent.agt_calls_talk_time_avg" style="font-weight:normal"></td>
<td ng-bind="agent.agt_calls_talk_time_total" style="font-weight:normal"></td>
<td ng-bind="agent.agt_calls_hold_time_total" style="font-weight:normal"></td>
</tr>
</tbody>
</table>
</div>
Here is the directive
part1.directive('myPostRepeatDirective', function() {
return function(scope, element, attrs,window) {
let buttons = document.querySelectorAll('div.wrap')
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("scroll", function () {
console.log('test scroll')
var translate = "translate(0," + (this.scrollTop - 1) + "px)";
this.querySelector("thead").style.background = 'white'
let x = this.querySelectorAll("thead th")
if (this.scrollTop > 0) {
for (i = 0; i < x.length; i++) {
event.stopPropagation();
x[i].style.border = "1px solid #ddd";
}
} else {
for (i = 0; i < x.length; i++) {
event.stopPropagation();
x[i].style.border = "";
var translate = "translate(0," + (this.scrollTop) + "px)"
}
}
this.querySelector("thead").style.transform = translate;
})
}
}
})
The problem is that the event listener scrolling value sometimes stays the same when I scroll the virtual repeat container, for example I scroll the table body from the first md-repeat element, then i go down the the last md-repeat element and it has the same css translate value.. Looks like value is applied when new md-virutal repeat element is rendered.
Thank you in advance.
I'm trying to get the src attribute of an html image. It seems like I can find the img element in the DOM but the src attribute is undefined, any ideas why?
HTML:
<table id="comboTable" style="width: 100%; height: 100%; margin-bottom: 10px;" data-bind="click: $root.selectCombo">
<tr>
<td>
<img class="selector" src="~/Images/roundOffButton.png" style="position: absolute;margin-left: -57px; margin-top: -35px;" />
</td>
<td style="height: 35px;">
<table style="width: 100%; background-color: #0097D8;padding:5px;">
<tr style="padding:5px;">
<td style="height: 36px; padding-left: 14px; font-weight: bold;color: black; margin: 1px; width: 70%; text-align:left;">
<span data-bind="text: Description" style="padding-left: 5px;" />
</td>
<td style="width: 30%;padding:8px; text-align: center;color: white; background-color:black;">
<span data-bind="text: formatCurrency(Price)" style="font-size: 14px; white-space: nowrap;
font-weight: bold;" />
</td>
</tr>
</table>
</td>
</tr>
</table>
Javascript:
var comboSpan = $("span:contains('" + description + "')");
var img = $(comboSpan).closest(".selector");
alert('Image object - ' + img);
var src = $(img).attr('src');
alert(src); //src is undefined
Working Demo
Use a valid selector for img, img and span have different parent, so you can't use closest() directly in this case.
Also comboSpan,img is already a jQuery objects. You don't need it like $(comboSpan)
Use .closest('#comboTable') as your hierarcy has a table inside a table.
<table>
<tr>
<td>
<img> //You need this.
</td>
<td>
<table>
<tr>
<td>
<span> //You have this.
</td>
</tr>
</table>
</td>
</tr>
</table>
Final code:
var comboSpan = $("span:contains('" + description + "')");
var img = comboSpan.closest('#comboTable').find('.selector'); //Change this line
alert('Image object - ' + img);
var src = img.attr('src');
alert(src); //src is undefined
You need to find closest tr and then .selector img :
var comboSpan = $("span:contains('" + description + "')");
var img = $(comboSpan).closest("tr").find(".selector");// find tr and then img
alert('Image object - ' + img);
var src = $(img).attr('src');
alert(src); //src is undefined
You first try to find tr and then it's child img (i.e .selector)
var img = $(comboSpan).closest('tr').find('.selector');
Try this:
var comboSpan = $("span:contains('" + description + "')");
var img = $(comboSpan).closest('tr').find('.selector');
alert('Image object - ' + img);
var src = $(img).attr('src');
alert(src);
Use this:
var img = comboSpan.closest('tr').find('.selector');
// no need to wrap comboSpan with jquery as comboSpan is already a jquery object
Check it out with this.
$('.img1 img').attr('src');
Simply you use as below:
var src = $('.selector').attr('src');
alert(src);
My answer is belove
$('.img1 img').attr('src');
Scenario:
I have a results table with a checkbox, when the checkbox is checked, the content of the row(actually 2 columns concateneted only, are copied to a new div, with the job code and job name). This works pretty well, and I am avoiding duplicated already.
However, in the new results div, I am creating an anchor tag to remove the div itself.
After the div has been removed, I should be able to add the selected job again with the checkbox.
Please note that there are many jobs in the results table, so putting the flag to false again will not work.
Also if you find a better title for this question, please let me know
//On every checkbow that is clicked
var flag = false;
$("#ctl00_PlaceHolderMain_myGrid input").change(function () {
if (this.checked && flag === false) {
flag = true;
var jobCode = $(this).parent().parent().parent().find("td:eq(2)").text()
var jobName = $(this).parent().parent().parent().find("td:eq(1)").text()
var displayvalue = jobCode.toUpperCase() + " - " + jobName.toUpperCase();
AddSelectedJob(jobCode, displayvalue);
//$(this).unbind('change'); //Unbind the change event so that it doesnt fire again
FillSelectedJobs();
}
});
//Add selected job in the results div
function AddSelectedJob(id, display) {
//create a div for every selected job
$("[id$=ResultsDiv]").append('<div class="selectedjobs" id=' + id + '>' + display + 'Remove selected job</div>');
}
//Removes the selected job from the resutls div
function removeSelectedJob(el) {
$(el).parent().remove();
}
The generated html is like this:
<div>
<div style="height: 300px; overflow: auto; float: left">
<div>
<table cellspacing="0" cellpadding="4" id="ctl00_PlaceHolderMain_myGrid" style="color:#333333;width:100%;border-collapse:collapse;">
<tr style="color:White;background-color:#5D7B9D;font-weight:bold;">
<th scope="col"> </th><th scope="col">JobCode</th><th scope="col">JobName</th><th scope="col">JobPartner</th><th scope="col">JobManager</th><th scope="col">ClientName</th>
</tr><tr style="color:#333333;background-color:#F7F6F3;">
<td>
<input id="ctl00_PlaceHolderMain_myGrid_ctl02_CheckBox1" type="checkbox" name="ctl00$PlaceHolderMain$myGrid$ctl02$CheckBox1" />
</td><td>jobcode01</td><td>jobname</td><td>xx</td><td>xx</td><td>xx</td>
</tr>
</table>
</div>
</div>
<div style="margin-top: 0px; margin-left: 10px; float: left">
<span>Selected :</span>
<div id="ResultsDiv" style="margin-top: 0px">
</div>
</div>
Firstly I suggest some changes to your HTML. Separate out the styles from your DOM and place them in classes.
This makes sure there is separation of concerns
HTML
<div>
<div class="divMain">
<div>
<table cellspacing="0" cellpadding="4"
id="ctl00_PlaceHolderMain_myGrid" class="table">
<tr class="rowHead">
<th scope="col"> </th>
<th scope="col">JobCode</th>
<th scope="col">JobName</th>
<th scope="col">JobPartner</th>
<th scope="col">JobManager</th>
<th scope="col">ClientName</th>
</tr>
<tr class="row">
<td>
<input id="ctl00_PlaceHolderMain_myGrid_ctl02_CheckBox1"
type="checkbox"
name="ctl00$PlaceHolderMain$myGrid$ctl02$CheckBox1"
data-flag="false" />
</td>
<td>column1</td>
<td>column2</td>
<td>column3</td>
<td>column4</td>
<td>column5</td>
</tr>
</table>
</div>
</div>
<div class="m0 selected">
<span>Selected :</span>
<div id="ResultsDiv" class="m0"></div>
</div>
CSS
.divMain{
height: 300px;
overflow: auto;
float: left
}
.table{
color:#333333;
width:100%;
border-collapse:collapse;
}
.rowHead{
color:White;
background-color:#5D7B9D;
font-weight:bold;
}
.row{
color:#333333;
background-color:#F7F6F3;
}
.m0{
margin-top: 0px;
}
.selected{
margin-left: 10px;
float: left
}
Javascript
$("#ctl00_PlaceHolderMain_myGrid input").change(function () {
// Next cache your selector
// so that you need not crawl the DOM multiple times
var $this = $(this),
$row = $this.closest('.row'),
currFlag = Boolean($this.data('flag'));
// As there might be multiple jobs , a single flag variable
// will not work. So you can set a data-flag attribute on the
// input that stores the current value
if (currFlag === false && this.checked) {
// Set the corresponding flag to true
$this.data('flag', true);
var jobCode = $row.find("td:eq(2)").text(),
jobName = $row.find("td:eq(1)").text(),
displayvalue = jobCode.toUpperCase() + " - "
+ jobName.toUpperCase(),
inputId = $this.attr('id')
// Pass the input name too as you need to set the value of
// the corresponding flag value again as you can add it multiple times
AddSelectedJob(jobCode, displayvalue, inputId);
FillSelectedJobs();
}
});
//Add selected job in the results div
function AddSelectedJob(id, display, inputId) {
//create a div for every selected job
// Use the inputId to save it as a data-id attribute
// on anchor so that you can set the value of the flag after
// removing it
var html = '<div class="selectedjobs" id=' + id + '>' + display ;
html += '<a href="javascript" data-id="'+ inputId
+'">Remove selected job</a></div>';
$('[id$=ResultsDiv]').append(html);
}
// Remove the inline click event for the anchor and delgate it to the
// static parent container
$('[id$=ResultsDiv]').on('click', 'a', function(e) {
var $this = $(this),
$currentCheckbox = $this.data('id');
// Set the flag value of the input back to false
$('#'+ $currentCheckbox).data('flag', false);
e.preventDefault(); // prevent the default action of the anchor
$this.closest('.selectedjobs').remove();
});
function FillSelectedJobs() {
//save values into the hidden field
var selectedJobs = $("[id$=ResultsDiv]").find("[class$='selectedjobs']");
var returnvalue = "";
for (var i = 0; i < selectedJobs.length; i++)
returnvalue += selectedJobs[i].id + ";";
$("[id$=HiddenClientCode]").val(returnvalue);
}
Check Fiddle