I have created a webpage that have some big divs in it.
I have a button on that page. On the click of that button I want the current div to change and bring the next div up.
I have written some code but unfortunately it's not working :(
HTML:
<div class="tutorial">
<p class="heading">Tell us about yourself</p>
<div class="body">
<table>
<tr>
<td>
<label for="full_name">What's your full name?</label>
</td>
</tr>
<tr>
<td>
<input type="text" name="full_name" id="full_name" placeholder="Full Name" />
</td>
</tr>
<tr>
<td>
<br/>
</td>
</tr>
<tr>
<td>
<label for="about">Describe yourself:</label>
</td>
</tr>
<tr>
<td>
<textarea id="about" name="about" rows="5" cols="40" placeholder="Share you hobbies, interests and more about yourself"></textarea>
</td>
</tr>
<tr>
<td width="900px" height="60px"></td>
<td>
<button id="next" class="btn">Next</button>
</td>
</tr>
</table>
</div>
</div>
<div class="tutorial hidden">
<p class="heading">Tell us about yourself!</p>
<div class="body">Body</div>
</div>
<div class="tutorial hidden">
<p class="heading">Tell us about yourself!</p>
<div class="body">Body</div>
</div>
<div class="tutorial hidden">
<p class="heading">Tell us about yourself!</p>
<div class="body">Body</div>
</div>
<div class="tutorial hidden">
<p class="heading">Tell us about yourself!</p>
<div class="body">Body</div>
</div>
JS:
$(function () {
var tutorials = $("div.tutorial");
var idNumber = 1;
tutorials.each(function () {
$(this).attr("id", idNumber);
idNumber++;
});
var nextButton = $("#next");
$(nextButton).on('click', function () {
var currentTutorial = $("div.tutorial").not(".hidden");
var currentTutorialId = currentTutorial.prop("id");
currentTutorial.addClass("hidden");
var nextTutorialId = currentTutorialId++;
var nextDiv = null;
if ($("div.tutorial").is("#" + nextTutorialId)) {
var nextDiv = $("div.tutorial");
}
nextDiv.removeClass("hidden");
});
});
Removed CSS to shorten the question's length. :)
What I want:
I want the next button to hide the current div and bring up the very next div after it.
What I have done:
var currentTutorial = $("div.tutorial").not(".hidden");
var currentTutorialId = currentTutorial.prop("id");
currentTutorial.addClass("hidden");
var nextTutorialId = currentTutorialId++;
var nextDiv = null;
if ($("div.tutorial").is("#" + nextTutorialId)) {
var nextDiv = $("div.tutorial");
}
nextDiv.removeClass("hidden");
You are trying to select by id, however I don't see any id for the .tutorial divs. However, you could simply use the next jQuery function to get the nextSibling of the current div. You also have to make sure that there's at least one div without the .hidden class initially.
E.g.
$('div.tutorial:not(.hidden)').addClass('hidden').next().removeClass('hidden');
You need to remove the id from your buttons and instead use a class and change your selector for the click binding. As sugessted by #koala_dev.
You can use prev() and next() functions like
$(nextButton).on('click', function () {
var currentTutorial = $("div.tutorial").not(".hidden");
var currentTutorialId = currentTutorial.prop("id");
currentTutorial.addClass("hidden");
currentTutorial.next('div').show();
nextDiv.removeClass("hidden");
});
Related
The HTML for the form is :
<form id="flowform" class="form" role="form" autocomplete="off">
<table id="add-flow-level" class="table table-striped table-borderless" style="width: 100%">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="col-sm-4">
<label class="required ">Min Amount</label>
<input type="text"
id="minAmount" name="minAmount" class="form-control min"
style="border-radius: 1rem; width: 183px;"
maxlength="100" required="required"
/>
<!-- onfocus = "maxAmountCheck(this.id);" -->
</div>
</td>
<td>
<div class="col-sm-4">
<label class="required ">Max Amount</label>
<input
type="text" id="maxAmount" name="maxAmount"
class="form-control max"
style="border-radius: 1rem; width: 183px;"
maxlength="100" required="required" />
<!-- onfocus = "maxAmountCheck(this.id);"/ -->
</div>
</td>
<td>
<div class="col-sm-4">
<label class="required">Approver</label>
<select class="form-control" id="approver" name="approver"
style="border-radius: 1rem; width: 183px;"
required="required" >
<!-- onfocus = "approverCheck(this.id);" -->
<option th:value="0">Select User</option>
<option th:each="usersList : ${usersList}"
th:value="${usersList.id}"
th:utext="${usersList.firstName +' '+ usersList.lastName}" />
</select>
</div>
</td>
<td>
<a href="#" id="addFlowLevelRow" class="btn btn-primary btn-label-left addFlowLevelRow" title="Add Next" style="margin-top: 18px;">
<i class="fa fa-plus" aria-hidden="true"></i>
</a>
</td>
</tr>
</tbody>
</table>
<br>
<div class="row">
<label class="control-label col-sm-5" style="margin-top: 8px;"></label>
<div class="col-sm-2">
<input type="submit" class="btn btn-primary btn-label-left"
value="Save" id="submitbtnflow" name="submitbtnflow"
style="border-radius: 1rem;">
</div>
<p id="msg" style="color: green;"></p>
</div>
</form>
js file
var countOfRows =1;
$(".addFlowLevelRow").click(function() {
var remv = "<a href='#' id='removeFlowLevelRow' class='btn btn-primary btn-label-left removeFlowLevelRow' title='Remove Row' style='margin-top: 33px;'><i class='fa fa-minus' aria-hidden='true'></i></a>";
var txt = $(this).closest("tr").find('#removeFlowLevelRow').attr('href');
if (txt == undefined && countOfRows < 5) {
var newRow = $(this).closest("tr").clone(true).appendTo("#add-flow-level").append(remv);
if(countOfRows == 4)
{
document.getElementsByClassName("addFlowLevelRow")[4].style.display = "none";
console.log("Removal of - button at row = "+countOfRows);
}
countOfRows++;
console.log("Number of row = "+countOfRows);
}
else if(countOfRows < 5){
var newRow = $(this).closest("tr").clone(true).appendTo("#add-flow-level");
if(countOfRows == 4)
{
document.getElementsByClassName("addFlowLevelRow")[4].style.display = "none";
console.log("Removal of - button at row = "+countOfRows);
}
countOfRows++;
console.log("Number of row =" +countOfRows);
}
var input = document.getElementsByClassName('max');
newRow.find('.min').val(input.value);
newRow.find('.max').val("");
newRow.find('#approver').val(0);
});
$(document).on('click', '#removeFlowLevelRow', function(e) {
console.log("view----");
$(this).closest("tr").remove();
countOfRows--;
console.log("After - Button count is = "+countOfRows);
});
$('#approver').on('change', function() {
alert("alerrt called");
var select = document.getElementById('approver');
var value = select.options[select.selectedIndex].value;
alert(value);
var index = value;
if (index > -1) {
// ${usersList}.splice(index, 1);
}
alert("ye ky tha"+select.value);
//return ${usersList};
});
I want that Super Admin to be disabled for the 2nd row and show values other than super Admin in that drop down.
Whenever the user clicks on + button it creates a clone of the row.
I have not created the new row separately but I want the new drop down to not have the value that are selected in the first drop down and this should go till 5 rows.
id's in the DOM should always be unique otherwise it can lead to strange behaviour in the page
so firstly you need to give each row's "approver" select element a separate id e.g. approver0,1,2... (or just remove the id) and instead have a common class for these elements e.g. "form-control approver"
Then in your onchange function, loop through the approver class and disable the select options that don't appear, here is some psuedo code to start working with
var a = document.getElementsByClassName("approver")
//loop through all approver select elements
for(i in a) {
if(a[i] = this) {
//do nothing if we loop to the element that has just been changed
}
else {
//if the approver select isn't the one we've just changed, loop through the options
options = a[i].childNodes
for(j in options){
if(options[j].value = this.value) {
//if the option matches the one we've just selected disable it
options[j].setAttribute("disabled")="disabled"
}
else {
//Otherwise re-enable it so we don't disable all elements by changing the selection
options[j].removeAttribute("disabled")
}
}
In this rudimentary example changing the next approver option will overwrite disabling the previous selection so you may need to also keep track of what has been selected in all other drop downs. but hopefully this gets you started
I have many checkboxes with same class name and below each there is a hidden date field.
I need to show the div with the date field and select different date.
in the begging I need to add 30 days from today when the checkbox is checked by default, then the user can change the date.
When I click to first choice and change the date is ok....but when I click to another the first date field takes the default value. Any suggestions?
html
#foreach (var item in Model)
{
<tr>
<td>
<div>
#Html.CheckBox(item.Title, new { #class = "chkPages", Value = item.ID }) #item.Title
</div>
<div class="extrafields">
<div class="DurationDisplayDate">
<input name="DurationDisplayDate" class="DurationDisplayDate" />
</div>
</div>
</td>
</tr>
-----------------------------
$('.chkPages').change(function () {
if (this.checked)
{
var dateStr = new Date();
dateStr.setDate(dateStr.getDate() + 30)
dateStr = dateStr.getDate() + "/" + (dateStr.getMonth() + 1) + "/" +
dateStr.getFullYear();
$(this).closest('div').next('.extrafields').fadeIn('slow');
//How can I change the next input field?
$(".DurationDate").val(dateStr);
}
else {
dateStr = "";
$(this).closest('div').next('.extrafields').fadeOut('slow');
$(".DurationDate").val(dateStr);
}
The main problems here are:
You are using "DurationDate" when the class is called "DurationDisplayDate"
You are selecting all elements with that class instead of just the relevant one in that row
An easy solution to this is to reuse the code you already have that's selecting the extras container for animation to find the relevant input e.g.
const extras = $(this).closest('div').next('.extrafields')
extras.find('.DurationDisplayDate').val(dateStr)
extras.fadeIn('slow')
Full working example:
$(document).ready(function() {
$('.chkPages').change(function() {
if (this.checked) {
var dateStr = new Date()
dateStr.setDate(dateStr.getDate() + 30)
dateStr = `${dateStr.getDate()}/${dateStr.getMonth() + 1}/${dateStr.getFullYear()}`
const extras = $(this).closest('div').next('.extrafields')
extras.find('.DurationDisplayDate').val(dateStr)
extras.fadeIn('slow')
} else {
const extras = $(this).closest('div').next('.extrafields')
extras.find('.DurationDisplayDate').val('')
extras.fadeOut('slow')
}
})
})
.extrafields {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>
<div>
<input type="checkbox" class="chkPages" />
</div>
<div class="extrafields">
<div class="DurationDisplayDate">
<input name="DurationDisplayDate" class="DurationDisplayDate" />
</div>
</div>
</td>
</tr>
<tr>
<td>
<div>
<input type="checkbox" class="chkPages" />
</div>
<div class="extrafields">
<div class="DurationDisplayDate">
<input name="DurationDisplayDate" class="DurationDisplayDate" />
</div>
</div>
</td>
</tr>
<tr>
<td>
<div>
<input type="checkbox" class="chkPages" />
</div>
<div class="extrafields">
<div class="DurationDisplayDate">
<input name="DurationDisplayDate" class="DurationDisplayDate" />
</div>
</div>
</td>
</tr>
</table>
I can't find the average of all the inputs. My code only reads the input that i stated in html, but doesn't read the other dynamic ones.
Heres my code:
$(document).ready(function(){
// adds a new row
$(".addCF").click(function(){
$("#customFields").append('<tr valign="top"><th scope="row"><label for="customFieldName">Custom Field</label></th><td><input type="text" class="code" id="customFieldName" name="customFieldName[]" value="" placeholder="Input Name" /> Add Remove</td></tr>');
});
// deletes the row
$("#customFields").on('click','.remCF',function(){
$(this).parent().parent().remove();
});
$("#customFields").on('click','.add',function(){
$("#customFields").append('<tr valign="top"><th scope="row"><label for="customFieldName">Custom Field</label></th><td><input type="text" class="code" id="customFieldName" name="customFieldName[]" value="" placeholder="Input Name" /> Add Remove</td></tr>');
});
$("#click").click(function(){
var isbn = document.getElementById('customFieldName').value;
alert(isbn / $("input").length)
$("#averageGrade").text("Average Grade: " + isbn)
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="form-table" id="customFields">
<tr valign="top">
<th scope="row"><label for="customFieldName">Custom Field</label></th>
<td>
<input type="text" class="code" id="customFieldName" name="customFieldName[]" placeholder="Input Name" />
Add
</td>
</tr>
</table>
<button id = "click" class = "btn btn-primary" >Hi</button>
<p id = "averageGrade">Average Grade:</p>
Please help!
Thanks!
Each element.id must be unique - please change customFieldName to a class, and then iterate over the inputs and calculate the average. Also, you can reuse the same class for all "add" buttons and save that string in a variable so you don't have to paste it multiple times.
let inputTemplate = '<tr valign="top"><th scope="row"><label>Custom Field</label></th><td><input type="text" class="customFieldName code" name="customFieldName[]" value="" placeholder="Input Name" /> Add Remove</td></tr>';
$(document).ready(function() {
// adds a new row
$("#customFields").on('click', '.addCF', function() {
$("#customFields").append(inputTemplate);
});
// deletes the row
$("#customFields").on('click', '.remCF', function() {
$(this).parent().parent().remove();
});
$("#click").click(function() {
let fields = $('.customFieldName'),
total = 0;
for (let field of fields)
total += Number(field.value);
let average = total / fields.length;
$("#averageGrade").text("Average Grade: " + average);
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="form-table" id="customFields">
<tr valign="top">
<th scope="row"><label>Custom Field</label></th>
<td>
<input type="text" class="customFieldName code" name="customFieldName[]" placeholder="Input Name" />
Add
</td>
</tr>
</table>
<button id="click" class="btn btn-primary">Hi</button>
<p id="averageGrade">Average Grade:</p>
First of all, you need a way to select all the fields. Since id must (should) be unique, you could use the name or the class .code and remove id="customFieldName".
Then, getElementById, as its name suggests, returns one element. You need to select them all! If you're using class names, you can use getElementsByClassName, or querySelectorAll, or, since you're already using jQuery, just $(".code"), along with a loop to read each input's value (it you use jQuery, you can also use each()).
var sum=0,count=0,average;
$(".code").each(function() {
var value=parseInt($(this).val());
//You may want to validate the field
if(!isNaN(value)) sum+=value;
count++;
});
average=sum/count;
...
As many has pointed out (including myself in the comment section), you are going about using the wrong selector. id is a unique selector, meaning that the script will look at the first instance of the id and then stop immediately after.
What you need to do is use a selector that goes through every occurance of its instance. This is why class selectors exist. That will be the first fix in your code.
How I would go about calculating the average, personally, would be to make an array and push(); the values of the grades into the array. We will also need to do a parseInt() to make sure that our values are in fact handled as numbers. Otherwise, they'll be interpreted as strings.
You will then need to loop through the array, sum the values and divide by the length of the array.
HTML Example:
<div class="row">
<div class="col-12">
<table class="table form-table" id="customFields">
<tr valign="top">
<th scope="row"><label>Custom Field</label></th>
<td>
<input type="number" class="customFieldName" placeholder="Input Number" />
Add
</td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-md-4">
<button id="calcAvrgBtn" class="btn-primary">Calculate average grade</button>
</div>
<div class="col-md-4">
<p id="averageCalc"></p>
</div>
</div>
jQuery Example:
$('.addCF').on("click", function() {
$("#customFields").append('<tr valign="top"><th scope="row"><label>Custom Field</label></th><td><input type="number" class="customFieldName" placeholder="Input Number" /> Remove</td></tr>');
});
$(document).on("click", "a.remCF" , function() {
$(this).parent().parent().remove();
});
$('#calcAvrgBtn').on("click", function() {
let gradeArr = [];
$('.customFieldName').each(function() {
gradeArr.push(parseInt($(this).val()));
});
let total = 0;
for(var i = 0; i < gradeArr.length; i++) {
total += gradeArr[i];
}
let avg = total / gradeArr.length;
$('#averageCalc').text("The average grade is: "+avg);
});
Codepen example can be found here.
Snippet Example:
$('.addCF').on("click", function() {
$("#customFields").append('<tr valign="top"><th scope="row"><label>Custom Field</label></th><td><input type="number" class="customFieldName" placeholder="Input Number" /> Remove</td></tr>');
});
$(document).on("click", "a.remCF" , function() {
$(this).parent().parent().remove();
});
$('#calcAvrgBtn').on("click", function() {
let gradeArr = [];
$('.customFieldName').each(function() {
gradeArr.push(parseInt($(this).val()));
});
let total = 0;
for(var i = 0; i < gradeArr.length; i++) {
total += gradeArr[i];
}
let avg = total / gradeArr.length;
$('#averageCalc').text("The average grade is: "+avg);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-12">
<table class="table form-table" id="customFields">
<tr valign="top">
<th scope="row"><label>Custom Field</label></th>
<td>
<input type="number" class="customFieldName" placeholder="Input Number" />
Add
</td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-md-4">
<button id="calcAvrgBtn" class="btn-primary">Calculate average grade</button>
</div>
<div class="col-md-4">
<p id="averageCalc"></p>
</div>
</div>
I have a Bootstrap Tab and a Table within the Tab and within the Table, a row with input fields. The problem I am experiencing is when I have multiple rows within the table only the first row values get pulled. I am using 'closet' and 'find' but I'm not getting the desired values. What am I doing wrong?
<ul class="nav nav-tabs nav-justified itemTab">
<li>Inbox</li>
<li>Outbox</li>
</ul>
<div class="tab-content itemTab">
<div class="tab-pane fade in" id="tab5">
<table class="table table-condensed" id="utable">
<th>Location</th>
<th>Department</th>
<th>HD Number</th>
#foreach (var item in Model.items)
{
<tr class="#item.Id">
<div class="accordian-body collapse in" id="#item.Id">
<input type="text" class="form-control" id="loc">
<input type="text" class="form-control" id="dept">
<input type="text" class="form-control" id="hdnum">
</div>
<div class="row">
<div align="center">
<input type="submit" value="Transfer" class="btn btn-success" onclick="MoveItem(#item.Id)" id="moveButton" data-url="#Url.Action("Submit", "Item")" />
</div>
</div>
</tr>
}
</table>
</div>
<div class="tab-pane fade in" id="tab6">
#Html.Action("Outbox", "Item")
</div>
function MoveItem(id) {
var row = $('#' + id).closest('.itemTab');
var loc = $(row).find('#loc').val();
var dept = $(row).find('#dept').val();
var hdnum = $(row).find('#hdnum').val();
}
First, wrap the id value in quotes when generating parameter for MoveItem call:
onclick="MoveItem('#item.Id')"
Second, change your repeating id's to classes and go up only as far as the parent tr:
<input type="text" class="form-control" class="loc">
function MoveItem(id) {
var row = $('#' + id).closest('tr');
var loc = $(row).find('.loc').val();
}
Your closest
var row = $('#' + id).closest('.itemTab');
gets the tab - but all of the "rows" are in that tab.
Instead, get the "row"
var row = $('#' + id).closest('tr');
then the finds will find the item in the relevant row.
I am developing a web with Angular, Ninja, HTML5 and Javascript. My problem is the following: I have a Ninja controller (ProjectController) where I render a list of projects to the HTML. I would like to show this list with the names of the projects with Angular. All the examples I have seeing about this, they made the list manually like this:
(function() {
var app = angular.module('projectStore', []);
app.controller('ProjectController', function(){
this.projects = gems ;
});
var gems = [
{ name: 'Azurite' },
{ name: 'Bloodstone' },
{ name: 'Zircon'}
];
})();
This is my code:
ProjectController.java
public Result getList(final FlashScope flashScope, final Session rawSession, final ProjectData registerRequest) {
log.info("getting project List");
List<Record1<String>> list = jCtx.jooq().select(PROJECT.PROJECT_NAME).from(PROJECT).fetch();
return Results.html().template("/views/ProjectController/projects.ftl.html").render("projects", list.toString());
}
rendered HTML projects.ftl.html
<#import "../layout/defaultLayout.ftl.html" as layout>
<#layout.myLayout "Home page">
<form name ="test" action="/projects" method="post" ng-app="projectStore">
<table id = "table_projects_header">
<tr>
<td>Projects</td>
<td style="padding-right:10px; padding-left:40px"> <input type="button" value=" + " onclick="addRow('table_projects')" /> </td>
<td> <input type="button" value=" - " /> </td>
</tr>
<tr id = "table_projects_list">
</tr>
</table>
<input type="submit" value="Add Project"/>
<div ng-controller="ProjectController as controller">
<div class="project row" ng-repeat="project in controller.projects">
<h3>
{{project}}
</h3>
</div>
</div>
</form>
</#layout.myLayout>
And I would like to do something like this:
app.js
(function() {
var app = angular.module('projectStore', []);
app.controller('ProjectController',function(){
this.projects = **get projects from rendered html** ;
});
})();
Is that possible??Thank you in advance!
HTML
<form name ="test" action="/projects" method="post" ng-app="projectStore">
<table id = "table_projects_header">
<tr>
<td>Projects</td>
<td style="padding-right:10px; padding-left:40px"> <input type="button" value=" + " onclick="addRow('table_projects')" /> </td>
<td> <input type="button" value=" - " /> </td>
</tr>
<tr id = "table_projects_list" class="renderValues">
</tr>
</table>
<input type="submit" value="Add Project"/>
<div ng-controller="ProjectController as controller">
<div class="project row" ng-repeat="project in controller.projects">
<h3>
{{project}}
</h3>
</div>
</div>
</form>
You can do like is:
(function() {
var app = angular.module('projectStore', []);
app.controller('ProjectController',function(){
this.projects=[];
//javascript way
var elements = document.getElementsByClassName('renderValues');
for (var index in elements)
{
var element = elements[index];
this.projects.push(element.innerHTML);
}
//jQuery way
/* var elements = document.getElementsByClassName('');
$('.renderValues').each(function(){
this.projects.push($(this).text());
});*/
});
})();