how to traverse between <td> and <tr> element? - javascript

I have a html table structure below:
<table>
<tr><td>ABC</td></tr>
<tr>
<td><input class="inp"/></td>
<td><input class="inp"/></td>
</tr>
<tr><td><input class="inp"/></td></tr>
<tr><td><input class="inp"/></td></tr>
</table>
<button id="btn">Click me</button>
Then my purpose is let the focus always go to next the input field in class "inp" by button click. Here is my script:
var focused = null;
$(".inp").focus(function () {
focused = $(this);
}).first().focus();
$("#btn").click(function(e){
if (focused && focused.length) {
//this only works horizontally.
focused.parent().next().find(".inp").focus();
// this only works vertically.
//focused.closest("tr").next().find(".inp").focus();
}
});
I want to focus the second line after the last element in the first row. How do I combine those two statements?

You do this by using the JQuery .index() and .eq() functions on a wrapped set of all the input elements.
This moves the focus back to the first input when it is on the last input and the button is clicked.
$(function() {
var $inputs = $('.inp');
var index = null;
$inputs.focus(function() {
index = $inputs.index($(this));
});
$inputs.first().focus();
$('#btn').click(function(e) {
if (index != null) {
index = (index + 1) % $inputs.length;
$inputs.eq(index).focus();
}
});
});
jsfiddle
This version does not wrap the focus back to the first input.
$('#btn').click(function(e) {
if (index != null) {
if ((index + 1) < $inputs.length) {
$inputs.eq(index + 1).focus();
}
}
});
jsfiddle

Try this :
HTML
<table>
<tr>
<td>ABC</td>
</tr>
<tr>
<td>
<input class="inp" />
</td>
<td>
<input class="inp" />
</td>
</tr>
<tr>
<td>
<input class="inp" />
</td>
</tr>
<tr>
<td>
<input class="inp" />
</td>
</tr>
</table>
<button id="btn">Click me</button>
JS
// initial just focus on first input
$('.inp').first().focus();
// get all input
var all = $('.inp');
// get first input index and add one number for next focus
var index = (all.index(all.first()) + 1);
$('#btn').click(function () {
// if length of input same with current index
// defined into 0, (goes bact to first input)
// if does't wanna go back just remove this line
if (index == all.length) index = 0;
// focus next input
all.eq(index).focus();
index++;
});
DEMO

This code seems little nasty but it will do the job for you :D
$(document).ready(function() {
var focused = null;
$(".inp").focus(function() {
focused = $(this);
}).first().focus();
$("#btn").click(function(e) {
if (focused && focused.length) {
if ($(focused).closest('tr').find('td').length > 1 && $(focused).closest('td').next().length != 0) {
$(focused).closest('td').next().find('.inp').focus();
} else {
$(focused).closest('tr').next().find('.inp').focus();
}
}
});
});
And here is Plunker : http://plnkr.co/edit/Nm3wETpltRo6i7mAXPtj?p=preview

I have a fiddle that is jumping indexes until you reach the last one. If you want you can modify it to also go backwards.
http://jsfiddle.net/gyebua9e/
$('.inp').first().focus();
var index = 0;
var $inputs = $('.inp').length;
$('#btn').click(function() {
index += 1;
$('.inp').eq(index).focus();
});

Sorry this is a little confusing, what are you trying to accomplish with jumping between input fields on click?
Also are you just trying to always go to the next input no matter what the wrapper is? so if I click the second input it goes to the third input, if I click the first it goes to the second input? etc

Related

Passing a parameter to a function in Javascript

I need to create a Javascript function (using a loop) that receives a value as a parameter from a function call in HTML and in response passes back the image of the back of a playing card however many times the value of the parameter is.
For example, if I pass the value 5 to the function, I should get back 5 images of the back of the card from the function displayed on the HTML page inside an existing table.
Here is what I have so far. Can someone please point me in the right direction as to where I'm going wrong (Thank you in advance for any help).
JS
function showCards(numcards) {
var data = "";
while (numcards < 5) {
data += "<td><img src="http://www.college1.com/images/cards/gbCard52.gif" NAME="card0"></td>";
numcards +=;
}
document.writeln(data);
}
HTML
<table border=0 style='margin:auto'>
<tr>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="Deal > > >">
</form>
</td>
<script type="text/javascript">showCards(5)</script>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="< < < Hit Me">
</form>
</td>
</tr>
</table>
There are mainly syntax errors in your code.
Either escape the double quote inside a string (ie. "\"") or use single quotes to declare your string.
You were trying to increment numcards using a wrong syntax. The correct syntax is numcards++.
But that's not what you want, you want to decrement it to 0 (ie. numcard--) to get your number of cards or count up to numcards using a for loop for example.
function showCards(numcards) {
var data = "";
for (var i = 0; i < numcards; i++) {
data += '<td><img src="http://www.college1.com/images/cards/gbCard52.gif" NAME="card0"></td>';
}
document.writeln(data);
}
showCards(5);
<table border=0 style='margin:auto'>
<tr>
<td>
<form><input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="Deal > > >"></form>
</td>
<td>
<form><input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="< < < Hit Me"></form>
</td>
</tr>
</table>
// where you want to append images tag
var table = document.querySelector('tbody');
// you can call this method on click event
function show(elem , param) {
var i = 0;
var data = document.createElement("tr");
var td = "";
while (param != i) {
td += "<td><img src='http://www.college1.com/images/cards/gbCard52.gif' NAME='card"+i+"'></td>";
i++;
}
data.innerHTML = td;
// append html tr node
elem.appendChild(data);
}
// calling when the script is loaded
show(table, 5);
<table>
<tbody>
</tbody>
</table>

Pass the name and value to JavaScript onClick function?

I have function that originally should disable group of check boxes if they are not checked. This function was designed to work onClick() and I was passing one argument onClick(this) from check box element. Now I need this function to be triggered on page load and I would need to pass the value from database. Tricky part is that I have more than one group of check boxes. Here is example of my HTML layout:
<tr>
<td>
<input type="checkbox" name="o_outcomeCk" id="o_firstOutcome" value="1" tabIndex="1" <cfif Trim(myData.o_outcomeCk) EQ 1>checked</cfif> onClick="ckChange('o_outcomeCk', 1)">First Outcome
</td>
<td>
<input type="checkbox" name="o_outcomeCk" id="o_secondOutcome" value="2" tabIndex="1" <cfif Trim(myData.o_outcomeCk) EQ 2>checked</cfif> onClick="ckChange('o_outcomeCk', 2)">Second Outcome
</td>
</tr>
<tr>
<td>
<input type="checkbox" name="o_progressCk" id="o_firstProgress" value="1" tabIndex="1" <cfif Trim(myData.o_progressCk) EQ 1>checked</cfif> onClick="ckChange('o_progressCk', 1)">First Progress
</td>
<td>
<input type="checkbox" name="o_progressCk" id="o_secondProgress" value="2" tabIndex="1" <cfif Trim(myData.o_progressCk) EQ 2>checked</cfif> onClick="ckChange('o_progressCk', 2)">Second Progress
</td>
</tr>
Above in each onClick function I have tried to pass the checkbox name and value. When user click on the check box I should disable one that is unchecked. Also when I load the page value from database will decide which check box is checked and one that is not check should be disabled at this time as well. Here is my Javascript function:
function ckChange(ckType, ckVal){
var ckName = document.getElementsByName(ckType);
var numChecked = 0;
var index = 0;
for(var i=0; i < ckName.length; i++){
if(ckName[i].checked){
numChecked++;
index = i;
}
}
for(var i=0; i < ckName.length; i++){
if(numChecked == 0){
ckName[i].disabled = false;
}else{
if(i != index){
ckName[i].disabled = true;
}
}
}
}
For some reason my function doesn't work as expected. I'm thinking also of passing the id each time I call this fucntion on click but then how that will work on page load? Here is what I do to call the function when user gets to the page:
<cfoutput>
ckChange('o_outcomeCk','#Trim(myData.o_outcomeCk)#');
ckChange('o_progressCk','#Trim(myData.o_progressCk)#');
</cfoutput>
Here I'm able to pass the name and value from database. I'm open for suggestions and different approach if that would be more efficient. My current code doesn't work. Thank you.
Here is a working solution. I had to remove your ColdFusion code, since the code editor doesn't support it, and I inserted some temporary JavaScript (the first four statements) to simulate some imported data.
If one of the check boxes is checked, the other will be disabled. If neither is checked, they will both be enabled. This solution should be scalable as well, if you add more check boxes to either group.
Try the example to make sure it does what you need it to. It's simulating the first box in o_outcomeCk and the second box in o_progressCk as being checked.
// simulate imported data & CF checkbox selecting
document.getElementsByName("o_outcomeCk")[0].checked = true;
document.getElementsByName("o_progressCk")[1].checked = true;
ckChange('o_outcomeCk',1);
ckChange('o_progressCk',2);
function ckChange(ckType, ckVal){
var ckName = document.getElementsByName(ckType);
var numChecked = 0; // counter
var index = 0; // which index is checked
for(var i = 0; i < ckName.length; i++){
// check which boxes in this set are checked
if (ckName[i].checked) {
// if the box that was clicked is checked
numChecked++;
index = i;
}
}
if (numChecked == 0) {
// enable both boxes
for (var i = 0; i < ckName.length; i++) {
ckName[i].disabled = false;
}
}
else {
// disable other box
for (var i = 0; i < ckName.length; i++) {
if (i != index) {
ckName[i].disabled = true;
}
}
}
}
<table>
<tr>
<td>
<input type="checkbox" name="o_outcomeCk" id="o_firstOutcome" value="1" tabIndex="1" onClick="ckChange('o_outcomeCk', 1)">First Outcome
</td>
<td>
<input type="checkbox" name="o_outcomeCk" id="o_secondOutcome" value="2" tabIndex="1" onClick="ckChange('o_outcomeCk', 2)">Second Outcome
</td>
</tr>
<tr>
<td>
<input type="checkbox" name="o_progressCk" id="o_firstProgress" value="1" tabIndex="1" onClick="ckChange('o_progressCk', 1)">First Progress
</td>
<td>
<input type="checkbox" name="o_progressCk" id="o_secondProgress" value="2" tabIndex="1" onClick="ckChange('o_progressCk', 2)">Second Progress
</td>
</tr>
</table>
UPDATE: Below is an alternate version of the JavaScript, which uses only one for loop. If you want to use it, just swap it out for the JavaScript code above. The only HTML that needs to be changed is the onclick attribute for each checkbox, which should be changed to onClick="ckChange(this)".
// simulate imported data & CF checkbox selecting
document.getElementsByName("o_progressCk")[1].checked = true;
ckChange("o_outcomeCk", 0);
ckChange("o_progressCk", 2);
function ckChange(that, val){
var isChecked = false;
var wasClicked = false;
var index = 0;
var ckType = that;
if (!!that.type) { // if called from a click
ckType = that.name;
wasClicked = true;
if (!!that.checked) {
index = that.value - 1;
isChecked = true;
}
}
var ckName = document.getElementsByName(ckType);
for(var i=0; i < ckName.length; i++){
if (isChecked) {
// if called from click and box was checked
if (index != i) {
ckName[i].disabled = true;
}
}
else if (wasClicked) {
// if called from click and box was unchecked
ckName[i].disabled = false;
}
else {
// if on load
if (val != 0) {
// one is checked
if (i != val - 1) {
ckName[i].disabled = true;
}
}
else {
// none checked
ckName[i].disabled = false;
}
}
}
}

Check and uncheck checkbox with Angular

In my form I have a table with checkbox in all of these columns. I have 3 <tr> and each <tr> has its ng-repeate calling the webservice to display the clones (Json data).
When I click on a checkbox I generate a js array which records id using this code :
checkoptions (array, model) {
angular.forEach(array, (value, key) => {
if (array[key].checked) {
model.push(array[key].id)
}
})
And in HTML :
<tr ng-repeat="developer in $ctrl.developers">
<td>{{developer.label}}</td>
<td>
<input type="checkbox" id="{{developer.id}}"
ng-change="$ctrl.checkoptions($ctrl.developers,$ctrl.employees.developers)"
ng-model="developer.checked">
<label for="{{developer.id}}"></label>
</td>
It works, but the problem is that when I uncheck a checkbox it is not removed from the js array
I included an else part to remove from the array:
http://jsfiddle.net/x9m1nqvp/1/
$scope.checkoptions = function (array, model) {
angular.forEach(array, (value, key) => {
if (array[key].checked) {
var index = model.indexOf(array[key].id);
if(index == -1)
model.push(array[key].id)
}
else {
var index = model.indexOf(array[key].id);
if(index >=0)
model.splice(index, 1);
}
})
While Everton's answer gets the job done, it is a bit redundant checking every item in the array, every time a single checkbox changes state. You don't really have to update for every single item in the array.
Here is an example, where only the checkbox that's actually toggled, is added or removed from the employees.developers array (Note: no need for the redundant angular.forEach):
$scope.checkoption = function (developer){
if (developer.checked) {
var index = $scope.employees.developers.indexOf(developer.id);
if(index == -1)
$scope.employees.developers.push(developer.id)
} else {
var index = $scope.employees.developers.indexOf(developer.id);
if(index >=0)
$scope.employees.developers.splice(index, 1);
}
}
and how this is used in the html:
<tr ng-repeat="developer in developers">
<td>{{developer.label}}</td>
<td>
<input type="checkbox" id="{{developer.id}}"
ng-change="checkoption(developer)"
ng-model="developer.checked">
<label for="{{developer.id}}"></label>
</td>
</tr>

How to get value of text box embeded in cell

I have the following code
<tr val='question'>
<td>
<input style='width: 500px' type='text' placeholder='Q.Enter your question here for radio button? '>
</tr>
How can i find the value of input box embedded in cell .
function saveUserDefQues(){
var table=document.getElementById("QuestionList");
var surveyquestionform=document.forms[0];
var count=$('#QuestionList tr').length
for (var i = 0; i<count; i++) {
var row = table.rows[i];
if(row.getAttribute('val')==='question')
{
var Cells = row.getElementsByTagName("td");;
}
}
}
document.querySelector('tr[val] > td > input').value;
Array.from(document.querySelectorAll('tr[val] > td > input')).forEach(function(entry, index, entries)
{
entry.value; // you may store the value OR process with it AS you see fit
});
Since you are using Jquery this can be done this way.
replace this line of code
var Cells = row.getElementsByTagName("td");
with
var Cells = $(row).find('td');
var inputValue = Cell.find('input').val(); // gives you value of input
Code Refactoring recommended
I would like to refactor your code as below
HTML
<tr data-val='question'> // use data-* attribute to add custom attributes into tags
<td>
<input style='width: 500px' type='text' placeholder='Q.Enter your question here for radio button? '>
</td> // close your td
</tr>
Script
function saveUserDefQues(){
var surveyquestionform = document.forms[0]; // not sure what this is for, so ill leave it as is.
$('#QuestionList tr[data-val="question"]').each(function(){ //loop all tr's which has the data-val set to question
var inputValue = $(this).find('td input').val(); //get the value of input
console.log(inputValue);
});
}
$("tr[val='question'] > td > input").val()
But first you need to write a valid HTML. </td> closing tag is missing. Also you need to put this tr in a <table>.
See this Plunker
function getResult(){
$( "tr" ).each(function( index ) {
console.log($(this).find('input').attr('placeholder') );
});
}

Strange behaviour with loop in Javascript

I've got a table-like structure with text inputs in which I am trying to make an entire row to be removed with all their children, but first passing the values of cells up one by one
in the rows below to keep IDs numbering structure.
The table structure is like this:
<table cellpadding=0>
<tr id="myRow1">
<td id="#R1C1">
<input class="myCell">
</td>
<td id="#R1C2">
<input class="myCell">
</td>
<td id="#R1C3">
<input class="myCell">
</td>
<td id="#R1C4">
<input class="myCell">
</td>
</tr>
<tr id="myRow2">
<td id="#R2C1">
<input class="myCell">
</td>
<td id="#R2C2">
<input class="myCell">
</td>
<td id="#R2C3">
<input class="myCell">
</td>
<td id="#R2C4">
<input class="myCell">
</td>
</tr>
<!-- ...and so on. -->
</table>
Having this table, when some event is triggered,I make this code run:
var rows = 1; // This value is updated when adding/removing a line
//This code runs from any <tr> by event keyup
if (event.altKey) { // I define here all Alt+someKey actions.
// Getting position values
var currentId = $(this).attr('id');
var row = Number(currentId.split('C')[0].substring(1));
var column = Number(currentId.split('C')[1]);
var belowVal;
if (event.which == 66) { //Case Ctrl+B
// If not the last row, start looping
if (rows > row) {
var diff = rows - row;
// Iteration over rows below
for (var i = 0; i < diff; i++) {
// Iteration over each column
for (var c = 1; c <= 4; c++) {
// here I try to get the value from column below
belowVal = $('#R'+(row+1+i).toString() +
'C'+c.toString()).val();
$('#R'+(row+i).toString()+'C' +
c.toString()).find('.myCell').val(belowVal);
}
}
}
$('#myRow'+rows.toString()).empty();
$('#myRow'+rows.toString()).remove();
rows--;
}
}
It works fine for removing the last row, but, when trying to remove an upper row, the values of current row and the ones below become blank instead of moving up. I made this code for each row below to pass it's values to the upper row, but it isn't doing what I wanted.
Why is this happening? I couldn't figure it out.
The problem seem to be, that the ids you are using to access the values are not the ids of the input elements, but rather the ids of the containing table cells.
Here an approach, which doesnt use the ids, but relies on the nodes structure instead, code not tested:
if (event.which == 66) {
var currentrow = $(this);
var currentinputs = currentrow.find('input.myCell');
while(var nextrow = currentrow.next('tr')) {
var nextinputs = nextrow.find('input.myCell');
currentinputs.each(function(index,element){
element.val(nextinputs.get(index).val());
});
currentrow = nextrow;
currentinputs = nextinputs;
}
currentrow.remove();
}
RESOLVED
Thanks to #JHoffmann, I was able to resolve my problem like this:
for (var c = 1; c <= 4; c++) {
// here I try to get the value from column below
belowVal = $('#R'+(row+1+i).toString()+'C'+c.toString())
.find('.myCell').val();
$('#R'+(row+i).toString()+'C'+c.toString())
.find('.myCell').val(belowVal);
}
In the line that assigns a value to belowVal, I forgot to call the method .find('.myCell') before calling .val(). That was the mistake that caused my code to fail, as #JHoffmann commented in his answer.

Categories