Altering value in one row dependant on another row's value - javascript

How do you alter a value in row to update on load dependant on another row's value?
For example in my table I have a column called Room Allocation and another called Action. If a row value Room Allocation column is set to Pending then I want the buttons for that particular row under Action to be Edit and Cancel but if it is anything else (i.e. not Pending) then the buttons should be Edit and Decline.
How can I go about doing this using jQuery? Here is my code below and I've included a fiddle here:
<table id="home_tbl">
<thead>
<tr>
<th>Module Code</th>
<th>Day</th>
<th>Start Period</th>
<th>Length</th>
<th>Room Preference</th>
<th>Room Allocation</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- dummy data starts here -->
<tr>
<td>COA101</td>
<td>Tuesday</td>
<td>11:00</td>
<td>2 hours</td>
<td>B.1.11</td>
<td>Pending</td>
<td><button class="cupid-green">Edit</button>
<button class="cupid-green">Cancel</button></td>
</tr>
<tr>
<td>COA201</td>
<td>Monday</td>
<td>10:00</td>
<td>1 hours</td>
<td>J001</td>
<td>J001</td>
<td><button class="cupid-green">Edit</button>
<button class="cupid-green">Cancel</button></td>
</tr>
<!-- dummy data ends here -->
</tbody>
</table>

How I would approach it depends on a couple of things: 1) what the difference between 'edit' and decline' is, and 2) who the audience is.
First, I assume that 'edit' and 'decline' are separate actions/URL endpoints? That is - the difference is what the button does, not just what the label is?
Next, if your audience is trusted (say, staff using an internal tool), you could include all three buttons in the markup, and show or hide them based on the 'pending' status. This is the easier option, but it won't work if you don't trust your audience.
If you don't trust them, you should never show the buttons to do the incorrect action - if the user has javascript disabled (or purposely disables it), they will be able to send a 'decline' request for rooms/bookings that they shouldn't be able to. In this case, you should create the table on the server, not using javascript/jQuery.
If you let me know that info, I can give you some examples of how to do either option!
Answer for a trusted audience:
OK - here's how to show/hide various buttons based on the status column. We'll use CSS and descendent selectors to do the showing/hiding, which makes the javascript very simple:
Here's the HTML you'll need for each row:
<tr class="booking">
<td>COA101</td>
<td>Tuesday</td>
<td>11:00</td>
<td>2 hours</td>
<td>B.1.11</td>
<td class="status">Pending</td>
<td class="action">
<button class="edit cupid-green">Edit</button>
<button class="decline cupid-green">Decline</button>
<button class="cancel cupid-green">Cancel</button>
</td>
</tr>
And the CSS:
/* Don't show the cancel button for normal rows, or the decline button for pending rows */
tr.booking button.cancel,
td.booking.pending button.decline {
display: none;
}
/* When the row is pending, show the cancel button */
tr.booking.pending button.cancel{
display: inline-block;
}
And finally, the jQuery/JS:
$(function(){
var bookingRows = $('table tr.booking'); //Find all the booking rows
bookingRows.each(function(){
var row = $(this); //Stash a reference to the row
//If you can add a class of 'pending' to the status <td>, this becomes even cleaner and nicer...
if (row.find('td.status').text().toLowerCase() == 'pending') { //Check the contents of the status column
row.addClass('pending'); //Add a class to the row so the CSS can do its thing...
}
});
});
To be honest, if you can make any changes on the server-side (which I hope you can, to make the JS easier as per my example), you can also just have the server create the rows with the correct buttons in the first place. Is there a reason this needs to be done on the client with JS?
Let me know if you need more detail or get stuck - I haven't tested this code, but it should work no problems.

Related

Change div color on checking all check boxes in hidden form

Have several problems and can't find solution. My code https://jsfiddle.net/46qybyrh/2/
Upper table HTML
<div class="block">
<table>
<tr>
<th>Nr.</th>
<th style="width: 200px">Task</th>
<th>Progresas</th>
<th></th>
</tr>
<tr>
<td>1</td>
<td>Air port scedules</td>
<td>0/3</td>
<td>
<button onclick="showDiv()">Expand</button>
</td>
</tr>
</table>
Hidden div
<div id="popup" class="popupbox">
<table class="block">
<tbody>
<tr>
<td></td>
<form>
<td>XML</td>
<td>
<span>Comment</span><br>
<textarea></textarea>
</td>
<td>
<span>Deadline</span>
<input type="date" value="2017-08-24">
</td>
<td>Done:<input type="checkbox"></td>
<td><input type="submit" value="Apply"></td>
</form>
</tr>
<tr>
<td></td>
<form>
<td>Scedules</td>
<td>
<span>Comment</span><br>
<textarea></textarea>
</td>
<td><span>Deadline</span>
<input type="date" value="2017-08-10">
</td>
<td>Done:<input type="checkbox"></td>
<td><input type="submit" value="Apply"></td>
</form>
</tr>
<tr>
<td></td>
<form>
<td>Infobox</td>
<td>
<span>Comment</span><br>
<textarea></textarea>
</td>
<td><span>Deadline</span>
<input type="date" value="2017-08-14">
</td>
<td>Done:<input type="checkbox"></td>
<td><input type="submit" value="Apply"></td>
</form>
</tr>
</tbody>
</table>
<button onclick="hideDiv()">close</button></div>
Main aims of this code should be:
When press apply on each row, hidden div should not hide. Only information like comment, date, check box should change.
When all 3 check boxes are selected, upper tables first row (1 Air port scedules 0/3) should change its background color.
If deadline is close (let say 5 days till deadline) entire row should change background color.
If deadline is passed entire row should change its background color.
I know its a lot to ask but maybe someone of you will guide me on each of this steps.
I took your fiddle and put it into a codepen and messed around with it for a while. I was able to do what you wanted with a lot of jQuery. To learn jQuery, try www.w3schools.com/jQuery.
Here is the codepen:
https://codepen.io/pen/Ojxzje
In a few short steps:
I removed all the <form> tags, <input type='submit'>, and <tbody> to make the code cleaner (the submit button was causing problems with hiding the div as mentioned by #AngeLOL.
I reformatted the lower table a bit just to make it cleaner for my jQuery to work nicely. (I added a header row and removed the text from the blocks)
I included the jQuery library
I renamed your jQuery functions and created one more (open(), close(), and apply(). They are called by the buttons respectively.
Inside the open() function, I showed the rows in the second table with the class if items-[ID OF LIST WE ARE IN]. This way there could be a clean list of all of the tasks instead of having a new table for every new list.
The open() function also changes the button from expand to hide which calls the close function.
The close() function just hides the second table and changes the name of the button back to expand.
The apply() function is run whenever you press the Apply button. It performs two checks:
Checks all of the checkboxes in the table rows labeled .details-[ID WE ARE WORKING WITH] and if they are all checked, selects the list's row in the upper table. It adds a green color to the background.
It then finds all the dates and compares them with today's date (thanks again #angeLOL. If the date is within 5 days, it selects the row the date was on and changes the color. If the date has passed or is today, it colors the row red.
It's a lot of code and a bunch of reorganization, so let me know if you are having trouble understanding it and I can help walk through my steps.
use <button type="button">Apply</button> instead <input
type="submit" value="Apply">
Give to those elements you want to change its color an "id" attribute, so change its color by using style propierty of element
document.getElementById("elementID").style.backgroundColor = "#colorcode"
Here is an example of how to compare dates.
Hidden div is initially hidden. When you submit the form, you reload the page, so it is hidden again. You may want to handle click on button or form submit, prevent default behavior, submit data via AJAX request and then update your UI without page reload.
<form onsubmit="return handleSubmit(this);">
...
<input type="checkbox" onchange="updateCheckboxesState();">
</form>
<script>
function handleSubmit(form) {
// send AJAX request here...
// manipulate DOM if needed in AJAX callback
return false; // prevent submit
}
function updateCheckboxesState() {
var checkboxes = document.querySelectorAll("form input[type=checkbox]");
for (var i = 0; i < checkboxes.length; i++) {
if (!checkboxes.item(i).checked) return; // break on first unchecked
}
// highlight the row here...
}
</script>
Similar flow can be applied to date inputs. The main idea is to update UI when value has been changed.
Background change can be achieved via changing element's inline style or changing it's class
var el = document.querySelector("div.block > table > tr");
el.style.backgroundColor = "#FF0000"; // inline
el.className = "highlighted"; // element class
Hope, this helps...

X-Editable re-enable after partial re-render

I have the following table on a laravel blade that uses x-editable to update some of its fields (note, this is my first ever PHP project so if there are better ways to do this, please share):
<table id="LinksTable" class="table table-bordered">
<thead>
<tr>
<th>Display</th>
<th>Link Display Name</th>
</tr>
</thead>
<tbody>
<?php $link_settings = Link_setting::whereNotNull('link_address')->get();?>
#foreach($link_settings as $link_setting)
<tr id="linkRow.{{$link_setting->id}}">
<td hidden="true">{{$link_setting->id}}</td>
<td><input id="linkD.{{$link_setting->id}}" name="is_displayed"
checked="{{$link_setting->is_displayed}}"
onChange="OnDisplayChange(this)" type="checkbox"></td>
<td><a href="#" class="listEdit" data-type="text"
data-column="display_name" data-url="./link_settings/update"
data-pk="{{$link_setting->id}}" data-title="change"
data-name="display_name">{{$link_setting->display_name}}</a>
</td>
</tr>
#endforeach
</tbody>
</table>
This renders fine the first time and I can edit the display name on any of the rows with it updating the database correctly.
My problem is that I have an "add" button that creates a new object in the database. After added, I need to reload the table to display this entry as well.
function RefreshTable() {
$('.listEdit').editable("destroy");
$( "#linksTableMainDiv" ).load(location.href + " #LinksTable");
$('.listEdit').editable();
}
The table re-renders fine, but the x-editable breaks, without errors that I can locate.
For anyone coming across this post, I ended up reworking this to add a row via javascript, rather than reloading the table. Adding $('.listEdit').editable(); after the table.appendChild(row) enables all the editable fields in the new row. Assigned data-pk=0 to each, and as part of the update controller, returned the id. I then update the row's data-pk elements upon success of the editable function.

How to pass parameters from dynamic table to the event handler without inline javascript hanlder

As I heard, I should avoid using inline javascript handler on html. e.g. onclick = "FUNCTION_NAME".
If I have a table that is generated dynamically, Each row has a button for its own.
If I don't use incline Javascript function, how can I pass some parameters from the table to the event handler?
Maybe passing the data from the table cell is not very hard. What if some data is not shown on the table cell (for security reason), for example, a secret ID number that is used internally within the application and is not supposed to exposure on the html (Setting it in the invisible cell in the table is not safe because people who knows html can still inspect it). How can we pass those data that is not shown on the table from dynamic table to event handler in this case?
If we use inline click attribute, i.e. onclick="javascript_function(parameter_1, parameter_2)" on each row, that's fairly easy to pass any data I want, and I do not need to show those kinds of secure data on the html in order to pass it.
If you use jQuery, I would recommand
<table class="with-val">
<td data-val="17">17 points</td>
</table>
and
$('.with-val').on('click', 'td', function() {
var val = $(this).data('val');
console.log(val) //17
});
This way (with the on(eventType, selector, handler) signature), you don't have to reset the events if rows are deleted or added,
and the markup is much lighter (and it is considred best practice, as you add only one event handler for the whole table).
Giving markup
<td class="val" data-val="17">17 points</td>
you can get value from binding like this:
$('.val').on('click', function() {
var val = $(this).data('val');
console.log(val) //17
});
For this:
Setting it in the invisible cell in the table is not safe because
people who knows html can still inspect it
You must not send secure data in any way to frontend. User can stop your code with breakpoints, debug or anything else, and get this data even when it is not visible in html. In addition this data will be visible in responses for the requests that browser send
You can use click event to call a function, that does the task of getting the value of any paramater you wish.
Hope this helps.
<td><button id="btn">Click me</button></td>
<td><input type="hidden" id="secret_id"></td>
$("#btn").click(function(){
var id = $("#secret_id").val();
alert(id);
});
This is a possible solution:
HTML:
<table border="1">
<thead>
<tr>
<th>HEAD1</th>
<th>HEAD2</th>
<th>HEAD3</th>
</tr>
</thead>
<tr>
<td class="hiddenField">row1 col1</td>
<td>row1 col2</td>
<td><button class="seeHidden">btn1</button></td>
</tr>
<tr>
<td class="hiddenField">row2 col1</td>
<td>row2 col2</td>
<td><button class="seeHidden">btn2</button></td>
</tr>
</table>
CSS:
th:nth-child(1), td:nth-child(1){
display: none;
}
jQuery:
$(".seeHidden").click(function(){
var hiddenField = $(this).parent()
.siblings("td.hiddenField")
.html();
alert(hiddenField);
});
Check this link jsfiddle to see a working example.
Hope it's useful!

Show/Hide Table Rows using Javascript classes

I have a table that kind of expands and collapses, but it's getting too messy to use it and IE and Firefox are not working properly with it.
So, here's the JavaScript code:
function toggle_it(itemID){
// Toggle visibility between none and ''
if ((document.getElementById(itemID).style.display == 'none')) {
document.getElementById(itemID).style.display = ''
event.preventDefault()
} else {
document.getElementById(itemID).style.display = 'none';
event.preventDefault()
}
}
And a Sample HTML:
<table>
<tr>
<td>Product</td>
<td>Price</td>
<td>Destination</td>
<td>Updated on</td>
</tr>
<tr>
<td>Oranges</td>
<td>100</td>
<td>+ On Store</td>
<td>22/10</td>
</tr>
<tr id="tr1" style="display:none">
<td></td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr id="tr2" style="display:none">
<td></td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
<tr>
<td>Apples</td>
<td>100</td>
<td>+ On Store</td>
<td>22/10</td>
</tr>
<tr id="tr3" style="display:none">
<td></td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr id="tr4" style="display:none">
<td></td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
</table>
The problem is that I use one ID for each and every and that's very annoying because I want to have a lot of hidden rows for each parent and a lot of parents, so it would be too many IDs to handle. And IE and FireFox are only showing the first Hidden Row and not the others. I suspect this happens because I've made it work by triggering all IDs together.
I think it would be better if I use Classes instead of IDs to indetify the hidden rows.
I'm really new to all of this so please try and explaining it in any kind of simply way. Also I've tried jQuery but wasn't able to get it.
It's difficult to figure out what you're trying to do with this sample but you're actually on the right track thinking about using classes. I've created a JSFiddle to help demonstrate a slightly better way (I hope) of doing this.
Here's the fiddle: link.
What you do is, instead of working with IDs, you work with classes. In your code sample, there are Oranges and Apples. I treat them as product categories (as I don't really know what your purpose is), with their own ids. So, I mark the product <tr>s with class="cat1" or class="cat2".
I also mark the links with a simple .toggler class. It's not good practice to have onclick attributes on elements themselves. You should 'bind' the events on page load using JavaScript. I do this using jQuery.
$(".toggler").click(function(e){
// you handle the event here
});
With this format, you are binding an event handler to the click event of links with class toggler. In my code, I add a data-prod-cat attribute to the toggler links to specify which product rows they should control. (The reason for my using a data-* attribute is explained here. You can Google 'html5 data attributes' for more information.)
In the event handler, I do this:
$('.cat'+$(this).attr('data-prod-cat')).toggle();
With this code, I'm actually trying to create a selector like $('.cat1') so I can select rows for a specific product category, and change their visibility. I use $(this).attr('data-prod-cat') this to access the data-prod-cat attribute of the link the user clicks. I use the jQuery toggle function, so that I don't have to write logic like if visible, then hide element, else make it visible like you do in your JS code. jQuery deals with that. The toggle function does what it says and toggles the visibility of the specified element(s).
I hope this was explanatory enough.
Well one way to do it would be to just put a class on the "parent" rows and remove all the ids and inline onclick attributes:
<table id="products">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Destination</th>
<th>Updated on</th>
</tr>
</thead>
<tbody>
<tr class="parent">
<td>Oranges</td>
<td>100</td>
<td>+ On Store</td>
<td>22/10</td>
</tr>
<tr>
<td></td>
<td>120</td>
<td>City 1</td>
<td>22/10</td>
</tr>
<tr>
<td></td>
<td>140</td>
<td>City 2</td>
<td>22/10</td>
</tr>
...etc.
</tbody>
</table>
And then have some CSS that hides all non-parents:
tbody tr {
display : none; // default is hidden
}
tr.parent {
display : table-row; // parents are shown
}
tr.open {
display : table-row; // class to be given to "open" child rows
}
That greatly simplifies your html. Note that I've added <thead> and <tbody> to your markup to make it easy to hide data rows and ignore heading rows.
With jQuery you can then simply do this:
// when an anchor in the table is clicked
$("#products").on("click","a",function(e) {
// prevent default behaviour
e.preventDefault();
// find all the following TR elements up to the next "parent"
// and toggle their "open" class
$(this).closest("tr").nextUntil(".parent").toggleClass("open");
});
Demo: http://jsfiddle.net/CBLWS/1/
Or, to implement something like that in plain JavaScript, perhaps something like the following:
document.getElementById("products").addEventListener("click", function(e) {
// if clicked item is an anchor
if (e.target.tagName === "A") {
e.preventDefault();
// get reference to anchor's parent TR
var row = e.target.parentNode.parentNode;
// loop through all of the following TRs until the next parent is found
while ((row = nextTr(row)) && !/\bparent\b/.test(row.className))
toggle_it(row);
}
});
function nextTr(row) {
// find next sibling that is an element (skip text nodes, etc.)
while ((row = row.nextSibling) && row.nodeType != 1);
return row;
}
function toggle_it(item){
if (/\bopen\b/.test(item.className)) // if item already has the class
item.className = item.className.replace(/\bopen\b/," "); // remove it
else // otherwise
item.className += " open"; // add it
}
Demo: http://jsfiddle.net/CBLWS/
Either way, put the JavaScript in a <script> element that is at the end of the body, so that it runs after the table has been parsed.
JQuery 10.1.2 has a nice show and hide functions that encapsulate the behavior you are talking about. This would save you having to write a new function or keep track of css classes.
$("tr1").show();
$("tr1").hide();
w3cSchool link to JQuery show and hide
event.preventDefault()
Doesn't work in all browsers. Instead you could return false in OnClick event.
onClick="toggle_it('tr1');toggle_it('tr2'); return false;">
Not sure if this is the best way, but I tested in IE, FF and Chrome and its working fine.
Below is my Script which show/hide table row with id "agencyrow".
<script type="text/javascript">
function showhiderow() {
if (document.getElementById("<%=RadioButton1.ClientID %>").checked == true) {
document.getElementById("agencyrow").style.display = '';
} else {
document.getElementById("agencyrow").style.display = 'none';
}
}
</script>
Just call function showhiderow()upon radiobutton onClick event
AngularJS directives ng-show, ng-hide allows to display and hide a row:
<tr ng-show="rw.isExpanded">
</tr>
A row will be visible when rw.isExpanded == true and hidden when
rw.isExpanded == false.
ng-hide performs the same task but requires inverse condition.

Add selected row from a table to another table with Jquery and MVC3

I am using MVC 3, EF Model First on my project.
In my View I have 4 tables that look likes these.
<div class="questionsForSubjectType">
<table>
<thead>
<tr>
<th>
Title
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
test
</td>
</tr>
</tbody>
</table>
</div>
users should be able to select and add to another table lets say the table is following:
<table id="CustomPickedQuestions>
/* <----- Questions that users chose from the other tables /*
</table>
What I am looking for is that when a users click on a row, the row shall get removed and added to the CustomPickedQuestions, When the row is added to that table, the user should also be able to remove it from CustomPickedQuestions Table and then that row shall go back to the Table it was before.
I now wonder how I can accomplish this with help of client-side jquery scripting.
You've got far too much irrelevant complexity in you code (for the specific question you ask). The title is good, but not the code. Rather than posting your complex project code, create the simplest possible reproduction of the problem using the least amount of code/methods/properties (with common names, that is ProductID, ProductName, etc). part 3 of my tutorial shows how to do this. See http://www.asp.net/mvc/tutorials/javascript/working-with-the-dropdownlist-box-and-jquery/adding-a-new-category-to-the-dropdownlist-using-jquery-ui

Categories

Resources