Unable to select the newly add button - javascript

I have a table with a default of 4 rows for user to input. please see the fiddle here http://jsfiddle.net/xaKXM/4/
When the user click on "Add More", the table will add new row to the "labelTable" with unique ID, as well as "configtableTable".
var displaymore = '<tr id=row'+currentIndex+'><td style="text-align: center">'+currentIndex+'</td>'+
'<td width="60%"><p id="label_row_'+currentIndex+'"></p></td>'+
'<td><button type="button" class="switch" id="switch_'+currentIndex+'"data-role="button" data-transition="fade">Activate</button></td></tr>';
When button "Submit" is pressed, user can see the description and the "Activate" button in the configtableTable. In order to make sure the Activate button is useful, i append thisIndex to a paragraph #ptest. It works for the first 4 default rows but does not work for the newly added rows (5 onwards).
What's wrong with my logic and code?
SOLVED: by creating a class "switch" and use .on()
$("#configtableTable").on('click', ".switch", function () {
thisIndex= $('td:nth(0)',$(this).closest('tr')).text();
if(thisIndex == ""){thisIndex = 0;}
$('#ptest').append(thisIndex);
$.post('/request', {responseNumber:$('#number_'+thisIndex).val(), key_pressed:"activate"});
});

there are two errors
1.In the generated code for "addmore", it should be following code for button
id="switch_' + currentIndex + '"
2.After creating new buttons, you have to add the click event for them.
I suggest the following code
$('#configsubmit').click(function () {
for (var x = 1; x <= currentIndex; x++) {
$('#label_row_' + x).html($('#label_' + x).val());
}
$('#configtable').show();
$("#configeditdiv").show();
$('#labels').hide();
$("#configtableTable [id^='switch_']:button").unbind('click');
$("#configtableTable [id^='switch_']:button").click(function () {
thisIndex = $('td:nth(0)', $(this).closest('tr')).text();
if (thisIndex === "") {
thisIndex = 0;
}
$('#ptest').append(thisIndex);
$.post('/request', {
responseNumber: $('#number_' + thisIndex).val(),
key_pressed: "activate"
});
});

Related

Setting events in loop works only for last element (jquery)

I have multiple button elements and for each of them I want to create a separate input element to load a picture. Button has an img element within that soon will have a source of loaded picture.
Input elements quantity should be the same as number of buttons.
As I looked through some tips here, I firstly created inputs in a loop than tried to trigger click event on each input in a separate loop.
But unfortunately in result I see that all button refer to last input
pix = $("button[id*='picture-add-']") // all buttons I have
for (var i = 0; i < pix.length; ++i){
i_selector = i+1
new_input = $('<input>', {
id:"file-input-" + i_selector.toString(),
type:"file",
name:"name",
style:"display: none;",
accept:"image/gif, image/jpeg, image/png, image/jpeg"}).appendTo('#addNew') // each input is added to main bootstrap window
}
for (let i = 0; i < pix.length; ++i){
i_sel = i+1
pic_element_id = pix[i].id
input_element_id = $('#file-input-' + i_sel.toString())[0].id
$('#' + pic_element_id).click(function(){
$('#' + input_element_id).trigger('click')
console.log(pic_element_id, 'pic_element_id')
console.log(input_element_id)
})
}
Any time I click any button console prints that I pressed the last button. What part of this could be wrong?

Why is one button overriding my other button even with unique classes?

I am new to javascript/jquery and have been stuck on this problem for a while. So I have two buttons, a clear button that will clear all forms in a row of a table and a reset button that holds all initial values for each row of the table.
The issue: So currently when I run the script the reset button will keep overriding the clear button. Meaning when I click on clear it will also act as a reset instead of clearing the row. I tried creating unique classes (.clear_button, .reset_button) to be called as you see here. I find it hard to troubleshoot javascript especially being new to it so why is this happening?
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(".clear_button").click(function(){
function my_clearFunction(i) {
document.getElementById("id_form-" + (i - 1) + "-Name").value = " ";
document.getElementById("id_form-" + (i - 1) + "-Start").value = "";
document.getElementById("id_form-" + (i - 1) + "-End").value = "";
document.getElementById("id_form-" + (i - 1) + "-Advanced").value = " ";
}
});
$(".reset_button").ready(function(){
$('#reset :input:not([type="button"])').each(function(idx, ele) {
ele.dataset.initvalue = ele.value;
});
$('#reset [type="button"]').on('click', function(e) {
// reset current row............
$(this).closest('tr').find(':input:not([type="button"])').each(function(idx, ele) {
// restore the initial value
ele.value = ele.dataset.initvalue;
})
});
});
});
</script>
Note: I understand the code is not uniform, for example, my clear button logic was not written in jquery. Sorry I couldn't attach a jsfiddle, this project is relatively pretty big and I use django to import my forms so it was difficult to set up. So any input would be greatly appreciated since I have been stuck on this for quite some time and can't seem to get it. It's also worth mentioning my input tags for the buttons so here they are.
<input type="button" class="clear_button" onclick="my_clearFunction({{ forloop.counter }})" value=" x ">
<input type="button" class="reset_button" value=" x ">
when I click on clear it will also act as a reset instead of clearing the row.
Your reset listener is declared as
$('#reset [type="button"]').on('click', function(e) {
...
})
It seems the #reset element contains both clear and reset buttons, so clicking in either will restore the initial values.
The clear button, also, has two handlers of its own. There is one declared in code which in turn declares a function (that isn't called in the handler itself) and an inline handler that tries to invoke said function. That shouldn't work, for it isn't visible from the global scope.
Instead of
$(button).on('click',(e)=>{
function doSomethingWith(i) {
...
}
doSomethingWith(e.target.id);
})
If should be
function doSomethingWith(i) {
...
}
$(document).ready(function(){
$(button).on('click',(e)=>{
doSomethingWith(e.target.id);
});
});
then it would be visible for the handler but also on the global scope, so you could call it using the inline "onclick"
<button onclick="doSomethingWith({{ forloop.counter }})" >
However, you shouldn't have an inline handler if you're also declaring one in JS. Since you're dealing with the reset button in code, stick to that approach for the clear button too.
Now, the approach you follow to clear a row needs for you to know the row relative index, and the inputs on each row, for which you compute their respective ids. Whereas, when it comes to reset the original values, you don't need to know anything:
$('.reset_button').on('click', function(e) {
// reset current row............
$(this).closest('tr').find(':input:not([type="button"])').each(function(idx, ele) {
// restore the initial value
ele.value = ele.dataset.initvalue;
})
});
The button needs only know it's inside the same <tr> element as other inputs whose value needs to be restored. It doesn't care about the index, the IDs, not even what inputs are in place, as long as they aren't buttons.
You should do the same to clear the values:
$('.clear_button').on('click', function(e) {
// reset current row............
$(this).closest('tr').find(':input:not([type="button"])').each(function(idx, ele) {
ele.value = "";
});
});
When it comes to storing the original value I'm also used to resort to jQuery.data . Anyway, for this use case you can perfectly stick to
input.dataset.initialValue = input.value
Instead of
$(input).data('initialValue',input.value)
As long as you keep in mind these approaches are not interchangeable. You can't set the initialValue with dataset then get it with jQuery.data or the other way around.
function randomTime() {
return [
Number(100 * Math.random() % 12).toFixed(0).padStart(2, '0'),
Number(100 * Math.random() % 60).toFixed(0).padStart(2, '0')
].join(':');
}
function addFormRow(player_name = 'N/A') {
let tr = $('<tr class="form_row">'),
name = $('<input type="text" name="name" class="name">'),
start = $('<input type="time" name="start" class="start">'),
end = $('<input type="time" name="end" class="end">'),
advanced = $('<input type="number" name="advanced" class="advanced">'),
clear = $('<button class="clear_button">Clear</button>'),
reset = $('<button class="reset_button">Reset</button>');
name.val(player_name);
start.val(randomTime());
advanced.val(parseInt(Math.random() * 100, 10))
end.val(randomTime());
for (let input of [name, start, end, advanced, clear, reset]) {
$('<td>').append(input).appendTo(tr);
}
tr.appendTo('#forms tbody');
}
addFormRow('player one');
addFormRow('player two');
addFormRow('player three');
$(document).ready(function() {
$('#forms tbody tr').each((index,tr)=>{
$(tr).find('input').each((idx,input)=>{
$(input).data('initialValue',$(input).val());
});
})
$(".clear_button").on('click', (e) => {
let $this = $(e.target),
tr = $this.closest('tr');
tr.find('input').each((index, input) => {
input.value = '';
});
});
$(".reset_button").on('click', (e) => {
let $this = $(e.target),
tr = $this.closest('tr');
tr.find('input').each((index, input) => {
$(input).val($(input).data('initialValue'));
});
});
});
.advanced {
width: 4em;
}
.name {
width: 9em;
}
.start,
.end {
width: 5.5em;
}
.form_row input {
height: 1.1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="forms">
<thead>
<tr>
<th>name</th>
<th>start</th>
<th>end</th>
<th>advance</th>
<th colspan="2">actions</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Your $(".clear_button").click() handler isn't doing anything. It defines a local function, but never calls it.
Instead of trying to call the function from onclick(), add a data attribute to buttons holding the index. Then the click handler can get this attribute and use it to find all the related elements that it needs to clear.
$(".clear_button").click(function() {
var i = $(this).data("rel-id");
document.getElementById("id_form-" + (i - 1) + "-Name").value = " ";
document.getElementById("id_form-" + (i - 1) + "-Start").value = "";
document.getElementById("id_form-" + (i - 1) + "-End").value = "";
document.getElementById("id_form-" + (i - 1) + "-Advanced").value = " ";
});
<input type="button" class="clear_button" data-rel-id="{{ forloop.counter }}" value=" x ">

Dynamically adding tags in HTML document on button click immediately reversed

I have very simple table with 3 columns that show 2 teams and their scores. Below the table there is a form that enables adding new teams and their scores to the table. The new row should be added only when given teams have different names and scores aren't negative.
I wrote the below code in JavaScript but it doesn't add the row - it is just showing new row only when confirm button is clicked. When it's not, the data disappear.
Can you look at my code and check what may be wrong with it?
I tried to add rows to the table without validate event and it worked perfectly fine.
document.addEventListener("DOMContentLoaded", function () {
var team1 = document.getElementById("team1");
var team2 = document.getElementById("team2");
var points1 = document.getElementById("points1");
var points2 = document.getElementById("points2");
var button = document.querySelector(".btn-primary");
var table = document.querySelector("table");
function validate(e) {
if (team1.value === team2.value) {
alert("Enter two differnt teams' names");
} else if (points1.value < 0 || points2.value < 0) {
alert("Points number cannot be negative");
} else {
var newRow = document.createElement("tr");
table.appendChild(newRow);
var newTeam1 = document.createElement("td");
newRow.appendChild(newTeam1);
newTeam1.innerHTML = team1.value;
var newTeam2 = document.createElement("td");
newRow.appendChild(newTeam2);
newTeam2.innerHTML = team2.value;
var newPoints = document.createElement("td");
newRow.appendChild(newPoints);
newPoints.innerHTML = points1.value + " - " + points2.value;
}
}
button.addEventListener("click", validate);
});
The problem here is that the button is part of a HTML <form>. Clicking the button submits the form and leads to the page being reloaded.
There are three different possible solutions to the problem. use either of those:
1) Place the button outside the form. Remove the <form></form> tags if you don't need them or place the button somewhere outside the <form></form> tags.
2) Specifically mark the button as being a button that does not submit the form:
<button type="button" class="btn-primary">Push me</button>
The type="button" prevents the button from submitting the form.
3) In the javascript handler of the button tell the button to not show its default behaviour like this:
function validate(e) {
{
// Your current code here
// Additional code to prevent button from showing default behaviour
e.preventDefault();
e.returnValue = false;
}
The e.returnValue = false; is for older browsers, the e.preventDefault(); is for newer browsers.

how to get click event of row which is generated on panel?

Can you please tell me how to get click event of row which is generated on panel .Actually I am able to get event of row which is generated on page.But i used this http://dbushell.com/2012/06/17/nestable-jquery-plugin/
I want to get click event of row which is generated in panel.
I make a simple demo to show nested list in panel. To open the panel there is button on header "open panel".
when you click "add test case button".it generate rows in panel as well in screen.When you click any of row it open new screen .there is another "add test case " button .it generate the nested list in panel
http://jsfiddle.net/VRPMj/1/
I get the click event of row which is on page like that .
$(document).on('click', '.clickTestCaseRow', function (e) {
var clickId = this.id;
hideDisplayView();
displayNewView(clickId);
alert('click')
e.stopPropagation();
})
When I do same like that on panel list it not work .:(
So there seem to be two problems with this
Firstly, the items in the side panel don't have the class clickTestCaseRow so the $(document).on('click'.. doesn't trigger on them.
var menuid = "menu_" + id;
$('#testSuit').append('<li class="dd-item submenu_h" id="' + menuid + '" ><div class="clickTestCaseRow dd-handle" id="' + menuid + '">' + id + '</div></li>')
Secondly, it seems the nested list plugin stops mousedown events on its items.
So I've disabled the nested list to check and it works now. Without the drag function of nestable though:
http://jsfiddle.net/VRPMj/3/
To really fix the issue you'd have to fiddle with the nestable plugin itself.
I've had a quick look at it and the issue seems to be on line 104.
This prevents the mousedown event on the items. So there's a starting point.
var onStartEvent = function(e)
{
var handle = $(e.target);
if (!handle.hasClass(list.options.handleClass)) {
if (handle.closest('.' + list.options.noDragClass).length) {
return;
}
handle = handle.closest('.' + list.options.handleClass);
}
if (!handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) {
return;
}
e.preventDefault(); // <=== Here
list.dragStart(hasTouch ? e.touches[0] : e);
};

how to show child element in right panel?

hi can you please tell me how show child element in right element .My function work fine first time But it fail second time .
I do the following steps
1) Press Add button 2 times.Generate row2 as well as submenu of firstLevel.
2) Expand menu option (+) Button.Click "menu_tc_1".It remove rows on right panel .and press add button it create nested submenu .
3) When you press again "menu_tc_1" it show same number of rows as many you click add button.
4) But when you click "First Level " it should show two rows because it have two child("menu_tc_1","menu_tc_2") .It is showing all rows.Because in array it gives all values.
I need show only child
jsFiddle
$(document).on('click', 'ul li > a', function (e) {
//first method..
console.log($(this).siblings().length);
var selEl = [];
$(this).closest('ul').find('li').each(function (idx, el) {
var id= el.id.replace('menu_','');
selEl.push(id);
});
// alert(id);
console.log('aaa' + selEl);
getViewFromPanel(selEl);
});
function getViewFromPanel(arr) {
console.log(arr);
$('#ultest').html('');
for (var i = 1; i < arr.length; i++) {
$('#ultest').append('<li id=' + arr[i] + '>' + arr[i] + '</li>');
}
}
See this updated fiddle.
The main problem is $(this).closest('ul').find('li').each(function (idx, el) {. find will look for all sub levels, that is why is displays all menus. You only want the children of the next ul:
$(this).closest('li').children('ul').children().each(function (idx, el) {
Also, you skip the first element (probably due to using find) in getViewFromPanel - it should start at 0 index:
for (var i=0;i<arr.length;i++){
There is a problem with the way that you set the active class so when you go back and click add, it is added to the wrong hierarchy. I am not sure what your intention is with the active class, but I think that you should clear the class $('.active').removeClass('active') and set it again when the hierarchy changes.

Categories

Resources