Tooltip showing hidden values in table format on hover - javascript

My site is set up in the following way:
4 user groups. Each user group can see different information. An example would be stock quantity for a store. So the user from London can't see the stock availability for Manchester. This information is taken from the database for EACH item in stock. So if you have a list of 20 items, their individual values will be displayed.
I would like to do the following:
If I, or anyone I give permission to, hovers over the "In Stock" column for their own store, a tooltip table must appear showing the current stock levels for the 3 other stores, for each individual product. So if I hover over item SKU-001, I will only see the stock availability for that item. I had an issue where it was displaying the whole list for each item.
I was thinking of this:
<table>
<tr>
<th>Store1></th>
<th>Store2></th>
<th>Store3></th>
<th>Store4></th>
</tr>
<?php foreach($this->products as $product) { ?>
<tr>
<td id="stock1" title="myFunction">Stock of Item 1st store</td> *If I hover/mouseover here, another table must appear showing only store name and values of "#stock2, #stock3 and #stock4* for the stock item I am hovering on.
<td id="stock2">Stock of Item 2nd store</td>
<td id="stock3">Stock of Item 3rd store</td>
<td id="stock4">Stock of Item 4th store</td>
</tr>
<?php } ?>
</table>
Here is some code I wrote:
function myFunction() {
var x = document.createElement("TABLE");
x.setAttribute("id", "table10");
document.body.appendChild(x);
var y = document.createElement("TR");
y.setAttribute("id", "myTr");
document.getElementById("myTable").appendChild(y);
var z = document.createElement("TD");
var t = document.getElementByID("riyadhbalance").value();
z.appendChild(t);
document.getElementById("myTr").appendChild(z);
However, for some reason this is not working. I have not found a way to include a tooltip. All the stock values are there for each individual item, so I just need to find a way to add the 3 values for the other stores and display them in a table format via a tooltip. That would be ideal.
So basically the tooltip should show the 3 values of the stores which are currently not on display, as the other 3 values are hidden. The user can only see their store's stock levels. But I would like to include this for myself as it would make it easier to view stock levels across the board.

Check this solution with jQuery and Bootstrap Working fiddle
You have four options:
1 - You can dynamically add it to your code on domReady (like the fiddle)
2 - You can directly print the needed html to make the plugin work. Check docs POPOVER or TOOLTIP
<button type="button" class="btn btn-lg btn-danger my_elements" data-toggle="popover" title="Popover title" data-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>
// and then, just call from javscript
<script>
$('.my_elements').popover(); // or $('.my_elements').tooltip();
</script>
3 - You can create it when you hover any element. Like the following example (this is particulary helpful if you have a lot of elements needing popover/tooltip, which would consume a lot of time and memory to init and handle)
<table>
<thead>
<tr>
<th>SKU</th>
<th>Description></th>
<th>Stock Tooltip</th>
<th>Stock Popover</th>
</tr>
</thead>
<tbody>
<tr><td>SKU-0001</td><td>This is a description for SKU-0001</td><td class="stock_t">5</td><td class="stock_p">5</td></tr>
</tbody>
</table>
<script>
$('.stock_p').on('mouseover', function(){
// get data from AJAX
// create table element
$(this).attr('title', table_element);
$(this).tooltip({
placement: 'top',
trigger: 'hover',
html: true,
container: 'body',
}).tooltip('show');
});
</script>
4 - with AJAX
<?php
// server side PHP
$other_stores_stock = [ "store_1" => 5, "store_2" => 20, "store_3" => 50 ];
header( 'Content-Type: application/json' );
echo json_encode( $other_stores_stock );
?>
//client side JS - like 1st example
<script>
$('.stock_p').on('mouseover', function(){
$.ajax({
url: your_url,
type: 'POST',
data: { your_data: 'get_stock_qty"},
dataType: "json",
async: false,
success: function (res) {
let table_html = '<table><tr><td>'+res['store_1']+'</td><td>'+res['store_2']+'</td><td>'+res['store_3']+'</td></tr></table>';
$(this).attr('title', 'Stock value for other Stores');
$(this).attr('data-placement', 'left');
$(this).attr('data-toggle', 'popover');
$(this).attr('data-trigger', 'hover');
$(this).attr('data-html', true);
$(this).attr('data-content', table_html);
$(this).popover('show');
}
});
});
</script>

Related

How do I get specific values from checked rows in MVC razor view?

Ok, so I have this partial view (part of an MVC application) which just displays data from a view in the database.
#model IEnumerable<TransportPlanner.Models.TRANSPORT_PLANNER_VIEW>
<table>
<tr>
<th>#Html.CheckBox("HeaderCheck")</th>
<th>#Html.DisplayNameFor(model => model.Status)</th>
....
<th>#Html.DisplayNameFor(model => model.Volume)</th>
<th>#Html.DisplayNameFor(model => model.Weight)</th>
....
</tr>
#foreach (var item in Model) {
<tr>
<th>#Html.CheckBox("RowCheck")</th>
<td>#Html.DisplayFor(modelItem => item.Status)</td>
....
<td>#Html.DisplayFor(modelItem => item.Volume)</td>
<td>#Html.DisplayFor(modelItem => item.Weight)</td>
....
</tr>
}
</table>
I want to be able to find a way in which I can get the values for the Volume and Weight fields of only the checked rows (after checking them), and add them to get the total (which is displayed but not stored).
For example, once I get the results displayed on screen, and I check 3 rows (having the values of 'weight' as 5, 10 and 15), then value displayed should be '30' (sum of the weights). Similarly, if I remove the checkbox for the row having weight as '5', then the value displayed should be '25'.
My front end skills are almost non-existent, and I have scourged over the internet for nearly 12 hours but not found a way to do it. I know that I need to either use JavaScript (or some flavour of it like JQuery) or Ajax (if I need the values updates dynamically as I check/uncheck them).
What is the best way to achieve this, without updating my model? I don't have the luxury of time because I am the only developer at my workplace, and this is the first step of a huge task I need to complete in 3 weeks.
Your #Html.CheckBox("RowCheck") is generating invalid html (duplicate id attributes). Replace it with
<input type="checkbox" class="checkbox" />
Then add class names to the <td> elements for Volume and Weight
<td class="volume">#Html.DisplayFor(modelItem => item.Volume)</td>
<td class="weight">#Html.DisplayFor(modelItem => item.Weight)</td>
And assuming you want to display the totals in the table footer, add the following html to the <table> element (note you should also use the <thead> and <tbody> in your table
<table>
....
<tfoot>
<tr>
<td></td>
....
<td id="totalvolume"><td>
<td id="totalweight"><td>
....
</tr>
</tfoot>
</table>
Then you can use javascript/jquery to handle the change event of the checkboxes, and sum the values in each row. Using jquery:
$('.checkbox').change(function() {
var totalVolume = 0;
var totalWeight = 0;
var selected = $('.checkbox:checked'); // get the selected checkboxes
$.each(selected, function(index, item) { // loop through the selected checkboxes
var row = $(this).closest('tr'); // get the containing tr element
totalVolume += Number(row.find('.volume').text());
totalWeight += Number(row.find('.weight').text());
})
// display the totals
$('#totalvolume').text(totalVolume);
$('#totalweight').text(totalWeight);
});
Note, the above code assumes the values of properties Volume and Weight are numeric (without any formatting)

Center a dynamically generated table cell in the window

I'm working on an employee directory that allows a user to search for an employee and show information about them in a tree/org-chart type layout. I'm using Google's Org Chart code to draw the chart. It displays each employee's contact card in a <td> with managers and subordinates above or below it in a different <tr>. The output looks something like this:
If an employee has more than a small handful of subordinates, the user has to scroll horizontally in order to see them all. Not a problem.
My problem is that if there are more than 10 or so, you lose sight of the employee you searched for completely and have to scroll right until you find them:
This seems like it would be annoying. I tried just dropping a <a name="anchor"> into the card and jumping to it on page load but it only scrolls far enough to barely put it on screen.
Ideally, it would center the card, putting it right in the user's focus.
Is there a way to jump directly to the employee in question when the page loads?
If it helps, here's a code snippet for what an individual card looks like:
<td>
<h1>Mike</h1>
<div class="cardBody">
<img src="Images/stock1.jpg" style="float:left; margin-right:5px;" />
<table class="data" cellpadding="0">
<tr>
<td><i class="fa fa-briefcase"></i></td>
<td><span style="color:red;">President</span></td>
</tr>
<tr>
<td><i class="fa fa-building"></i></td>
<td>Administration</td>
</tr>
<tr>
<td><i class="fa fa-globe"></i></td>
<td>Home Office</td>
</tr>
<tr>
<td><i class="fa fa-phone"></i></td>
<td>Ext. 2402</td>
</tr>
<tr>
<td><i class="fa fa-envelope"></i></td>
<td>Send Email</td>
</tr>
</table>
</div>
</td>
A little confused on what you have tried to far. Does jQuery work for you? If so, this solution seems simple enough.
$(container).scrollTo(target);
Now if you can pass your "target" through a url query. You should be able to parse and use it like so:
Note: This assumes you have a url like www.website/searchpage.html?i=targetID
Also: This is setup to work with IDs so change the code if you need to work with classes.
var params;
function parseURLParams(url) {
var queryStart = url.indexOf("?") + 1,
queryEnd = url.indexOf("#") + 1 || url.length + 1,
query = url.slice(queryStart, queryEnd - 1),
pairs = query.replace(/\+/g, " ").split("&"),
parms = {}, i, n, v, nv;
if (query === url || query === "") {
return;
}
for (i = 0; i < pairs.length; i++) {
nv = pairs[i].split("=");
n = decodeURIComponent(nv[0]);
v = decodeURIComponent(nv[1]);
if (!parms.hasOwnProperty(n)) {
parms[n] = [];
}
parms[n].push(nv.length === 2 ? v : null);
}
return parms;
}
$(document).ready(function(){
params = parseURLParams(window.location.href);
$("#Container").scrollTo("#"+params.i);
});
Hope this helps someone.
Edit:
I realize you want it to be centered which is going to be a little tricky. You're going to need your container to be much larger(or infinite?) than required for it to fit all the data, and then scroll to the position of the desired element, plus an offset for half the container's view able width, and half the element's width. Might just want to create an invisible element with an absolute position when you calculate this number. Then move the element to this position, and finally the screen to this element.
You could append the URL to so it jumps to the div with a specific ID. For example in the card code you posted you'd change the div to this:
<div class="cardBody" id="mikeCard">
Then change the link to the page to
Link to page with Mike's card centered
or if you want to link to that part from the same page just do
Jump to Mike's card

How to print data by current table on page in Laravel 5?

My problems are:
When I click the print button, it shows the data by text not in table.
I want to print data table depends on the current table show. means
here is on the current page has list of all data and select option.
When I select or filter table it still print all the data. The data
here is collected from database.
After logged in, why does the image for next page not show?
Here is my JavaScript:
<script lang='javascript'>
$(document).ready(function(){
$('#printPage').click(function(){
var data = '<input type="button" value="Print this page" onClick="window.print()">';
data += '<div id="div_print">';
data += $('#report').html();
data += '</div>';
myWindow=window.open('','','width=200,height=100');
myWindow.innerWidth = screen.width;
myWindow.innerHeight = screen.height;
myWindow.screenX = 0;
myWindow.screenY = 0;
myWindow.document.write(data);
myWindow.focus();
});
});
</script>
Blade template:
<tbody id="result">
#foreach($profiles as $profile)
<tr>
<td class="student_id" width="15%">{{$profile->student_id }}</td>
<td class="name" width="30%">{{$profile->student_name }}</td>
<td class="program" width="30%"> {{$profile->program }}</td>
<td class="faculty" width="25%">{{$profile->faculty }} </td>
</tr>
#endforeach
</tbody>
</table>
<p align="center"><button id="printPage">Print</button></p>
Rather than doing the method I suggest that you use a PDF generation plugin such as pdf-laravel.
PDF-LARAVEL :
to output to a file
$router->get('/pdf/output', function() {
$html = view('pdfs.example')->render();
PDF::load($html)
->filename('/tmp/example1.pdf')
->output();
return 'PDF saved';
});
Adding the functionality to your controller
class HomeController extends Controller
{
private $pdf;
public function __construct(Pdf $pdf)
{
$this->pdf = $pdf;
}
public function helloWorld()
{
$html = view('pdfs.example1')->render();
return $this->pdf
->load($html)
->show();
}
If you want to search for other options then go to packagist.org and search for "pdf laravel" and you will find some packages built for Laravel 5 PDF generation.
Answer to the question 2:
I want to print data table depends on the current table show. means
here is on the current page has list of all data and select option.
When I select or filter table it still print all the data. The data
here is collected from database
If you want to filter data and display there, you have two options, either filter data form the controller or you can use jQuery Datatables for that. Link here
All you have to do is:
Add the Js.
https://cdn.datatables.net/1.10.10/css/jquery.dataTables.min.css
Add the css
http://cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js
Call your table.
$(document).ready(function(){
$('#myTable').DataTable();
});
function printData()
{
var print_ = document.getElementById("table_name");
win = window.open("");
win.document.write(print_.outerHTML);
win.print();
win.close();
}
The above function will print the data of a table which are on the current page due to the window.open("") function.

Fill jQuery DataTables with drop down and PHP

I'm working with DataTables and this is my scenario:
1)I've got a drop down menu with some user's name and their proper ID;
2)I've got an empty DataTable;
3)I would like to detect user's ID selecting one row from drop drown menu, pass it to server_processing.php(DB query) using data: property of DataTables and display DB query's result back in Data Table.
Code for drop down:
<select id="selezione_user" name="selezione_user" class="select2 form-control">
<option value="">Seleziona</option>
<?php $query=mysql_query("SELECT user_id,nome FROM user ORDER BY nome",$conn);
while($row=mysql_fetch_array($query)){
echo "<option value='$row[user_id]'>$row[nome]</option>";
}?>
</select>
Code for DataTable (HTML):
<table class="table table-striped" id="prova">
<thead>
<tr>
<th>User</th>
<th>Comune</th>
<th>Mail</th>
<th>Stato</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Code for DataTable (JS)
$(document).ready(function() {
var oTable = $('#prova').dataTable( {
"processing": true,
"serverSide": true,
"ajax": {
"url": "scripts/server_processing.php",
"data": {
"user_id": null //set to show empty DataTable
}
},
});
$('#selezione_user').change(function() {
aoData.push({
"user_id": this.value
})
});
});
But the code above doesn't work and this problem is driving me crazy, I hope someone will help me.
Thanks to all.
Giacomo.
EDIT
I solved my problem using removing data: and changing DataTables(JQuery) function in this way:
$('#selezione_centri').change(function() {
var valore = this.value;
var string = ('scripts/server_processing.php?id_professionista='+valore);
table.ajax.url(string).load();
table.reload();
});
I think you should check the row
echo "<option value='$row[user_id]'>$row[nome]</option>";
Try changing it to
echo "<option value='".$row["user_id"]."'>".$row["nome"]."</option>";
This is somewhat explained here: Accessing arrays whitout quoting the key , the php array keys need to be quoted. This is merely a longshot here!
For more precise debugging (if this is not enough), you should provide the php code.

How to get html table values from multiple columns with single checkbox and submit to servlet?

I have html data table. I want to get values from multiple columns with single checkbox and when click on submit button values should go to servlet. Please help how to do this?
function refile(){
$('#resend').click(function() {
$("input:checked").each(function () {
var id = $(this).attr("id");
var messagePayload = $('#'+id).val();
var messageType = $('#msgType'+id).val();
alert("Payload Alert:"+ messagePayload);
alert("MessageType Alert:"+ messageType);
$.ajax({
type: "POST",
url: "http://localhost:8080/InterfaceMonitoring/ResendServlet",
data: {
messagePayload:messagePayload,
messageType:messageType
}
});
});
});
}
<c:otherwise>
<c:forEach items="${msgs}" var="msg" varStatus="count">
<tr id="check">
<td>
<input type="checkbox" id ="payloadMsg${count.index}" name="payload" value="${msg.messagePayload}">
</td>
<td></td>
<td>${msg.dob}</td>
<td></td>
<td>${msg.name}</td>
<td></td>
<td>
<div class="accordion">
<h3>Payload</h3>
<div id="payloadMsg${count.index}">${msg.messagePayload}</div>
</div>
</td>
<td></td>
<td>
<div id="msgType${count.index}">${msg.messageType}</div>
</td>
</tr>
</c:forEach>
</c:otherwise>
The problem is the way you try to get messageType.
Since you're using the ID of the input element, and prefixing it with #msgType it results in #msgTypepayloadMsgX so that element will never be found.
And since it's a DIV you're looking for you should use .html() to get the content.
Try adding data-index="${count.index}" to each input[checkbox] and get it in the script using $(selector).data('index') so that you can query for $('#msgType' + index)
And you should not make an ajax request for each row. Instead store the payloadMessage and messageType in an object and send it all to the backend at once, after iterating all rows.
An example could be:
Javascript
function refile(){
$('#resend').click(function() {
var payloads = [];
$('input:checked').each(function () {
var $this = $(this),
index = $this.data('index'),
$type = $('#msgType' + index);
payloads.push({
messageType: $type.html(),
messagePayload: $this.val()
});
});
if (payloads.length === 0) {
return;
}
$.ajax({
type: 'POST',
url: 'http://localhost:8080/InterfaceMonitoring/ResendServlet',
data: {
'payload': payloads
}
});
});
}
HTML
<tr id="check">
<td><input type="checkbox" id="payloadMsg${count.index}" data-index="${count.index}" name="payload" value="${msg.messagePayload}"></td>
<td></td>
<td>${msg.dob}</td>
<td></td>
<td>${msg.name}</td>
<td></td>
<td>
<div class="accordion">
<h3>Payload</h3>
<!-- Note that this ID is conflicting with the input#payloadMsg${count.index} -->
<div id="payloadMsg${count.index}">${msg.messagePayload}</div>
</div>
</td>
<td></td>
<td>
<div id="msgType${count.index}">${msg.messageType}</div>
</td>
</tr>
So, from what I've seen, on the front-end, at least, your code SHOULD work, but you've made it REALLY complex. . . . more complicated than you need it to be, I think. Again, while it should work, simplifying it will mean that there are much fewer places in the code where something could go wrong.
I think the best way to do this is make it easy on yourself:
flag the <div> elements that you want to retrieve with a class value that you can use to get their values (rather than relying on the unique IDs)
make the "unique" identifier of the message at the highest level in the table as you can (in this case, the <tr>
simplify your HTML attributes . . . you've got a lot of duplicate data and excess identifiers in your table structure. Try something like this:
HTML
<c:otherwise>
<c:forEach items="${msgs}" var="msg" varStatus="count">
<tr id="payloadMsg${count.index}">
<td>
<input type="checkbox" name="payload">
</td>
<td></td>
<td class="msg-dob">${msg.dob}</td>
<td></td>
<td class="msg-name">${msg.name}</td>
<td></td>
<td>
<div class="accordion">
<h3>Payload</h3>
<div class="msg-payload">${msg.messagePayload}</div>
</div>
</td>
<td></td>
<td>
<div class="msg-type">${msg.messageType}</div>
</td>
</tr>
</c:forEach>
</c:otherwise>
Once you've set that up, you have a much more simple structure, with all of the values that you could ever need, clearly identified. Now, you can pretty easily you can pretty easily get to the values that you need, using jQuery . . . just update your existing code to be something like this:
$(document).ready(function() {
$('#resend').click(function() {
$("input:checked").each(function () {
var currRow = $(this).closest("tr");
var currPayload = currRow.find(".msg-payload").text();
var currType = currRow.find(".msg-type").text();
alert("Payload Alert:"+ currPayload );
alert("MessageType Alert:"+ currType );
$.ajax({
type: "POST",
url: "http://localhost:8080/InterfaceMonitoring/ResendServlet",
data: {
messagePayload: currPayload,
messageType: currType
}
});
});
});
});
NOTE: You were using .val() instead of .text() to retrieve the text in the "type" <div> . . . .val() is only used with input elements.
Not knowing what you are doing on the back-end with this data, I can't really help you make sure that it is storing it correctly, but removing the reliance on the indexes to find the data that you want, should help simplify your logic a lot.
Also, if you ever want any other data from the row, you can capture it pretty easily now . . . for example:
var currMsg = currRow.attr("id");
var currDOB = currRow.find(".msg-dob").text();
var currName = currRow.find(".msg-name").text();
. . . after you have set the currRow value in your code, of course. :)
So, give that a try and see how things go. On the front-end, you should be good with this, at that point, you would need to just focus on the back-end and make sure that everything is working there.

Categories

Resources