I have one of the components label with the sample class tclick
<label class="btn btn-default tclick" data-tloc="value1" data-tkey="key1" >
<label class="btn btn-default tclick" data-tloc="value2" data-tkey="key2" >
<label class="btn btn-default tclick" data-tloc="value3" data-tkey="key3" >
Whenever click on any one component of label, class "checked" will be automatically added to label :
ex:
<label class="btn btn-default tclick checked" data-tloc="value1" data-tkey="key1" >
<label class="btn btn-default tclick checked" data-tloc="value2" data-tkey="key2" >
but i want get exactly data-tloc, data-tkey when label is click ?
i like code jquery and I need one solution ?
$('label.tclick').click(function() {
$(this).addClass('checked');
var tloc = $(this).data('tloc'),
tkey = $(this).data('tkey');
console.log(tloc, tkey);
});
.checked { color: red; }
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<label class="tclick" data-tloc="value1" data-tkey="key1">Label1</label>
<label class="tclick" data-tloc="value2" data-tkey="key2">Label2</label>
<label class="tclick" data-tloc="value3" data-tkey="key3">Label3</label>
Solution:
$('label.tclick').click(function(){
var tloc = $(this).data('tloc'),
tkey = $(this).data('tkey');
$(this).addClass('checked');
console.log('Tloc:' + tloc + ', Tkey: ' + tkey);
});
After 'checked' is automatically added and you just want the data attributes on click then try on change because if click executes before the checked class is added is(':checked') may not work:
$( "label.tclick" ).on('change', function() {
if($(this).is(':checked')){
console.log($(this).data('tloc'));
console.log($(this).data('tkey'));
}
});
Related
I am creating a HTML form for data entry that contains a couple of textboxes and function buttons.
There is also an add button that copies (clones) from a DIV template (id: w) for each "row" and appends to the end of the main DIV (id: t). On each row, there is a "X" button to remove the row and two arrow buttons to visually move the "row" up and down in the DOM.
The form is dynamically created from a database and the elements already on the page when the page is loaded and using jQuery 3.4.1, for the selecting and most of the DOM manipulation using the functionality of each rows buttons.
The "rows" are added to the container DIV and the elements are renamed depending on the counter which is expected. The "X" button deletes the "row", and moves all pre-existing rows up and down in the container DIV.
But for some unknown reason any new rows that are created I have to press the "up" button twice. The "down" button for the bottom row, is redundant and not functional.
I think it might have to do with the previousSibling and nextSibling returning the wrong Object type and causing a problem and failing the first time.
Any thoughts on how to fix or improve this functionality?
var rr = $("[id^=l]").length;
$(".data-up").click(function() {
var e = $(this).first().parent().parent().get(0);
moveUp(e);
});
$(".data-down").click(function() {
var e = $(this).parent().parent().get(0);
moveDown(e);
});
$(".remove").click(function() {
$(this).parent().parent().remove();
});
function add() {
rr += 1;
var a = $("#w").clone(true, true).removeAttr('id').removeAttr('style');
a.attr("datarow", "row" + rw);
a.find("input[data-field='l']").attr("id", "l" + rr).attr("name", "l" + rr).removeAttr("data-field");
a.find("input[data-field='s']").attr("id", "s" + rr).attr("name", "s" + rr).removeAttr("data-field");
a.appendTo("#t");
}
function moveUp(e) {
if (e.previousSibling) {
if (e.previousSibling === e.parentNode.children[0]) {} else {
e.parentNode.insertBefore(e, e.previousSibling);
}
}
}
function moveDown(e) {
if (e === e.parentNode.children[e.parentNode.children.length - 1]) {} else {
e.parentNode.insertBefore(e.nextSibling, e);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<button type="button" class="btn btn-secondary" ID="p" onclick="add();">Add</button>
<div id="t">
</div>
<div class="form-group row" id="w" style="display:none;" datarow="row">
<div class="col-sm-1"><input name="s" class="form-control txt-s col-form-label" id="s" type="text" readonly="true" data-field="s"></div>
<div class="col-sm-3"><input name="l" class="form-control txt-l" id="l" type="text" data-field="l"></div>
<div class="col-sm-2">
<button class="btn btn-danger mr-1 remove" type="button">X</button>
<button class="btn btn-info mr-1 data-up" type="button">↑</button>
<button class="btn btn-info data-down" type="button">↓</button>
</div>
</div>
With jQuery - use .closest() to find the current parent of the button. The find the .prev() or the .next() sibling. If the sibling exists use .insertBefore() or .insertAfter() to move the current parent before or after the sibling:
var rr = $("[id^=l]").length;
$(".data-up").click(function(e) {
var current = $(this).closest('.form-group'); // find the current parent
var target = current.prev(); // find the relevant sibling
if(target.length) { // if sibling exists
current.insertBefore(target); // insert the current item above it
}
});
$(".data-down").click(function() {
var current = $(this).closest('.form-group'); // find the current parent
var target = current.next(); // find the next sibling
if(target.length) { // if the next sibling exists
current.insertAfter(target); // insert the current item after it
}
});
$(".remove").click(function() {
$(this).parent().parent().remove();
});
function add() {
rr += 1;
var a = $("#w").clone(true, true).removeAttr('id').removeAttr('style');
a.attr("datarow", "row" + rr);
a.find("input[data-field='l']").attr("id", "l" + rr).attr("name", "l" + rr).removeAttr("data-field");
a.find("input[data-field='s']").attr("id", "s" + rr).attr("name", "s" + rr).removeAttr("data-field");
a.appendTo("#t");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<button type="button" class="btn btn-secondary" ID="p" onclick="add();">Add</button>
<div id="t">
</div>
<div class="form-group row" id="w" style="display:none;" datarow="row">
<div class="col-sm-1"><input name="s" class="form-control txt-s col-form-label" id="s" type="text" readonly="true" data-field="s"></div>
<div class="col-sm-3"><input name="l" class="form-control txt-l" id="l" type="text" data-field="l"></div>
<div class="col-sm-2">
<button class="btn btn-danger mr-1 remove" type="button">X</button>
<button class="btn btn-info mr-1 data-up" type="button">↑</button>
<button class="btn btn-info data-down" type="button">↓</button>
</div>
</div>
What's wrong in your code
The problem with the up button is e.previousSibling === e.parentNode.children[0] - the 1st element is always the first item in the collection, so this blocks you from moving an item above it. All you have to check is if there is a previousSibling for up, and nextSibling for down.
Fixed code + comments:
var rr = $("[id^=l]").length;
$(".data-up").click(function() {
var e = $(this).parent().parent().get(0); // first() is redundant - this is the only element in the collection
moveUp(e);
});
$(".data-down").click(function() {
var e = $(this).parent().parent().get(0);
moveDown(e);
});
$(".remove").click(function() {
$(this).parent().parent().remove();
});
function add() {
rr += 1;
var a = $("#w").clone(true, true).removeAttr('id').removeAttr('style');
a.attr("datarow", "row" + rr);
a.find("input[data-field='l']").attr("id", "l" + rr).attr("name", "l" + rr).removeAttr("data-field");
a.find("input[data-field='s']").attr("id", "s" + rr).attr("name", "s" + rr).removeAttr("data-field");
a.appendTo("#t");
}
function moveUp(e) {
if (e.previousSibling) { // just check if there's a previous sibling
e.parentNode.insertBefore(e, e.previousSibling);
}
}
function moveDown(e) {
if (e.nextSibling) { // just check if there's a next sibling
e.parentNode.insertBefore(e.nextSibling, e);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<button type="button" class="btn btn-secondary" ID="p" onclick="add();">Add</button>
<div id="t">
</div>
<div class="form-group row" id="w" style="display:none;" datarow="row">
<div class="col-sm-1"><input name="s" class="form-control txt-s col-form-label" id="s" type="text" readonly="true" data-field="s"></div>
<div class="col-sm-3"><input name="l" class="form-control txt-l" id="l" type="text" data-field="l"></div>
<div class="col-sm-2">
<button class="btn btn-danger mr-1 remove" type="button">X</button>
<button class="btn btn-info mr-1 data-up" type="button">↑</button>
<button class="btn btn-info data-down" type="button">↓</button>
</div>
</div>
Let's say I have div like this on my page:
<div style="padding-top:10px;" id="message2">
<p>More Links: <span class="fa fa-plus add"></span></p>
<div class="appending_div">
<div class="blog_links">
<p class="blog_linku_1">
Link URL 1: <input type="text" name="blog_linku_1[]"> Link Name 1: <input type="text" name="blog_linkn_1[]">
</p>
</div>
</div>
</div>
So simply if user click on + sign, it will add another input field just like this one with this script:
$(document).ready(function() {
var i = 2;
$('.add').on('click', function() {
var field = '<p class="link'+i+'">Link URL '+i+': <input type="text" name="blog_linku_'+i+'[]"> Link Name '+i+': <input type="text" name="blog_linkn_'+i+'[]"> <span class="glyphicon glyphicon-minus minus" id="minus'+i+'"></span></p>';
$('.appending_div').append(field);
i = i+1;
})
$('#minus'+i+'').click(function(){
$(".link"+i+"").remove();
});
})
And if you mention out, the extra links contains a remove symbol which is a - sign, and by clicking this sign, the paragraph which has the class link"+i+" should be removed.
And now the problem is that the remove icon does not work when you click on it. And the Console bar does not show any error message.
So what is your idea about this, how can I solve this problem?
First, it will be better to attach the event to a common class instead of using incremented values
Example :
var i = 2;
$('.add').on('click', function() {
var field = '<p class="link">Link URL ' + i + ': <input type="text" name="blog_linku[]"> Link Name ' + i + ': <input type="text" name="blog_linkn[]"> <span class="glyphicon glyphicon-minus minus">----</span></p>';
$('.appending_div').append(field);
i++;
});
NOTE: Since you're using input names as array [] you don't have to generate them with indexes.
You need to use the event delegation .on() when you attach the click event to .minus since the elements are generated dynamically :
$('body').on('click','.minus', function() {
$(this).closest('p').remove();
});
$(document).ready(function() {
var i = 2;
$('.add').on('click', function() {
var field = '<p class="link">Link URL ' + i + ': <input type="text" name="blog_linku[]"> Link Name ' + i + ': <input type="text" name="blog_linkn[]"> <span class="glyphicon glyphicon-minus minus">DELETE</span></p>';
$('.appending_div').append(field);
i++;
});
$('body').on('click', '.minus', function() {
$(this).closest('p').remove();
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="padding-top:10px;" id="message2">
<p>More Links: <span class="fa fa-plus add"></span></p>
<div class="appending_div">
<div class="blog_links">
<p class="blog_linku_1">
Link URL 1: <input type="text" name="blog_linku_1[]"> Link Name 1: <input type="text" name="blog_linkn_1[]">
</p>
</div>
</div>
</div>
<br>
<button class="add" type="button">Add</button>
I've restructured your code a bit. See below:
$(document).ready(function() {
var i = 2;
$('.add').on('click', function() {
$('<p class="link' + i + '">Link URL ' + i + ': <input type="text" name="blog_linku_[]" /> Link Name' + i + ': <input type="text" name="blog_linkn_[]"> <span class="fa fa-minus minus"></span></p>')
.appendTo('.appending_div');
i = i + 1;
});
$('.appending_div').on('click.remove', '.minus', function () {
$(this).parent()
.remove();
});
})
<link href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="padding-top:10px;" id="message2">
<p>More Links: <span class="fa fa-plus add"></span></p>
<div class="appending_div">
<div class="blog_links">
<p class="blog_linku_1">
Link URL 1: <input type="text" name="blog_linku_1[]"> Link Name 1: <input type="text" name="blog_linkn_1[]">
</p>
</div>
</div>
</div>
I've simplified the top portion of your code that adds the element to the screen. Since you are using jQuery you can combine a few of these steps with the chaining of their library functions.
For the event handling, because the elements are added dynamically, you need to delegate the events to the new elements. Recall that elements must be present on the page for the event to be bound. Otherwise, the events must be delegated to an existing element. jQuery will handle the abstractions and the "bubbling" of the events to the parent element.
You are adding the #minus element on $(".add") click, so when the DOM loads it cannot find the $("#minus"). You have to add the $("#minus") click function inside the $(".add") click.
Try the below code
$(document).ready(function() {
var i = 2;
$('.add').on('click', function() {
var field = '<p class="link'+i+'">Link URL '+i+': <input type="text" name="blog_linku_'+i+'[]"> Link Name '+i+': <input type="text" name="blog_linkn_'+i+'[]"> <span class="glyphicon glyphicon-minus minus" id="minus'+i+'"></span></p>';
$('.appending_div').append(field);
i = i+1;
$('#minus'+i+'').click(function(){
$(".link"+i+"").remove();
});
});
});
Somehow to onchange fuction does not trigger properly after I Switch the Radio button. Currently I get no log message with "circle uncheck" or "arrow uncheck". The HTML Looks like this:
var drawingArrow = document.getElementById('drawing-arrow-shape'),
drawingCircle = document.getElementById('drawing-circle-shape');
drawingCircle.onchange = function() {
console.log("on change circle btn");
if ($("#drawing-circle-shape").is(":checked")) {
console.log("circle checked");
} else {
console.log("circle uncheck");
}
};
drawingArrow.onchange = function() {
console.log("on change arrow btn");
if ($("#drawing-arrow-shape").is(":checked")) {
console.log("arrow checked")
} else {
console.log("arrow uncheck");
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-arrow-shape">
<i class="glyphicon glyphicon-arrow-right"></i>
</label>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-circle-shape">
<i class="glyphicon glyphicon-record"></i>
</label>
The issue is because the , after the second variable definition should be a ;. This is confusing the JS interpreter as it thinks the next statement will be a variable definition, when in fact it's a variable setter.
You should however note that you can improve your logic by using addEventListener() on the elements directly. You can then just use the this keyword to reference the element without having to use jQuery to select an element you already have a reference to. Try this:
document.getElementById('drawing-arrow-shape').addEventListener('change', function() {
if (this.checked)
console.log('arrow checked');
});
document.getElementById('drawing-circle-shape').addEventListener('change', function() {
if (this.checked)
console.log('circle checked');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-arrow-shape">
<i class="glyphicon glyphicon-arrow-right"></i>
</label>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-circle-shape">
<i class="glyphicon glyphicon-record"></i>
</label>
you need to change these 2 statements:
var drawingArrow = document.getElementById('drawing-arrow-shape');
drawingCircle = document.getElementById('drawing-circle-shape');
There was a ',' on the end of both which was causing the issue. Replacing that with ';' fixed it.
I made a small change in your Js and now it is working please check below changes I made
var drawingArrow = document.getElementById('drawing-arrow-shape');
var drawingCircle = document.getElementById('drawing-circle-shape');
Just removed comma and made separate variables.
var drawingArrow = document.getElementById('drawing-arrow-shape');
var drawingCircle = document.getElementById('drawing-circle-shape');
drawingCircle.onchange = function() {
console.log("on change circle btn");
if($("#drawing-circle-shape").is(":checked")) {
console.log("circle checked");
} else {
console.log("circle uncheck");
}
};
drawingArrow.onchange = function() {
console.log("on change arrow btn");
if($("#drawing-arrow-shape").is(":checked")) {
console.log("arrow checked")
} else {
console.log("arrow uncheck");
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-arrow-shape">
<i class="glyphicon glyphicon-arrow-right"></i>
</label>
<label class="btn btn-default btn-lg">
<input type="radio" name="drawing-shape" id="drawing-circle-shape">
<i class="glyphicon glyphicon-record"></i>
</label>
I am trying to implement a functionality that user can add and remove two text fields (ie heading, and description) using jquery, add more functionality is works fine but the removing order is not correct.
Hers is the fiddle that shows the problem
Jquery
var append = '<div><div class="form-group"> <label>Day 1</label><input type="text" value="" name="subHeading" class="form-control"></div>';
append += '<div class="form-group"> <label>Description</label> <textarea class="form-control" name="description"></textarea>';
append += '</div><button type="button" class="btn btn-danger remove" id="btnAddMore">Remove</button></div>';
$('#btnAddMore').click(function() {
$('#appendContent:last').before(append);
});
$('body').on('click', '.remove', function() {
//alert('ok');
$(this).parent().remove();
});
Also i need one more thing when a user is click add more button I am showing a label thay shows day 1 if adding another item the it will show day 2 and so on.
Update text of the label after append/remove
Give some class to identify parent element of container.
$('.days').text(function(index) {
return 'Day ' + (index + 1)
});
Updated Fiddle
give class to main div
var append='<div class="minus"><div class="form-group">
in jquery
$(this).closest('.minus').remove();
You can do,
$('#btnAddMore').click(function() {
var clone = $(append).clone()
$('#appendContent').append(clone);
clone.find(".form-group > label").text("Day " + $("#appendContent").children().length);
});
$('body').on('click', '.remove', function() {
//alert('ok');
$(this).parent().remove();
});
Fiddle
Make a copy of the newly created div using clone().
Then change the label inside the clone() using .find(".form-group > label").text()
Get the number of the current div by counting the children of "appendContentDiv"
var appendContentSize = $('#appendContent .appended-element').size();
$('#btnAddMore').click(function(){
var append='<div class="appended-element"><div class="form-group"> <label>Day '+appendContentSize+'</label><input type="text" value="" name="subHeading" class="form-control"></div>';
append+='<div class="form-group"> <label>Description</label> <textarea class="form-control" name="description"></textarea>';
append+='</div><button type="button" class="btn btn-danger remove" id="btnAddMore">Remove</button></div>';
$('#appendContent').append(append);
appendContentSize++
});
$('body').on('click','.remove',function(){
//alert('ok');
if(appendContentSize > 0){
$(this).parent().remove();
appendContentSize--
}
});
https://jsfiddle.net/giantomakin/wsm755vv/8/
Have a look attached snippet :
/* Latest compiled and minified JavaScript included as External Resource */
var append='<div><div class="form-group"> <label></label><input type="text" value="" name="subHeading" class="form-control"></div>';
append+='<div class="form-group"> <label>Description</label> <textarea class="form-control" name="description"></textarea>';
append+='</div><button type="button" class="btn btn-danger remove" id="btnAddMore">Remove</button></div>';
$('#btnAddMore').click(function(){
$('#appendContent:last').before(append);
var i=1;
$('input[type="text"]').each(function(){
$(this).prev().html('Day '+i);
$(this).attr('name', 'subHeading' + i);
$(this).attr('id', 'subHeading' + i);
i++;
});
});
$('body').on('click','.remove',function(){
//alert('ok');
$(this).parent().remove();
var i=1;
$('input[type="text"]').each(function(){
$(this).prev().html('Day '+i);
$(this).attr('name', 'subHeading' + i);
$(this).attr('id', 'subHeading' + i);
i++;
});
});
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button type="button" class="btn btn-primary"id="btnAddMore">Addmore</button>
<!--for append -->
<div id="appendContent">
</div>
<!--end append-->
</div>
As well as please have a look attached fiddle.
Demo fiddle
I have the following Javascript:
$("div.duplicate-fields:last-child").clone().find('input').each(function() {
this.name = this.name.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
this.value = "";
this.checked = false;
}).removeClass("active").end().appendTo("#duplicate-section");
Inside a .click() function. This works fine. However I have the following HTML in the cloned area:
<div class="btn-group" data-toggle="buttons"><label class="btn btn-default button-array "><input type="checkbox" name="select-sessions[3][1]" value="">Session 1</label>
<label class="btn btn-default button-array "><input type="checkbox" name="select-sessions[3][2]" value="">Session 2</label>
<label class="btn btn-default button-array "><input type="checkbox" name="select-sessions[3][3]" value="">Session 3</label>
<label class="btn btn-default button-array "><input type="checkbox" name="select-sessions[3][4]" value="">Session 4</label>
<label class="btn btn-default button-array active"><input type="checkbox" name="select-sessions[3][5]" checked="" value="">Session 5</label>
</div>
Now, in the above jQuery I have this.checked=false; which makes any cloned checkbox unchecked. But unfortunately, The label.button-array still has the class of active, which means it still looks like it is checked.
So I modified my jQuery function be like this:
$("div.duplicate-fields:last-child").clone().find('input').each(function() {
this.name = this.name.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
this.value = "";
this.checked = false;
}).find("label.button-array.active").each(function() {
$(this).removeClass("active");
}).end().appendTo("#duplicate-section");
Notice the new find() function added on to the first. However, It seems to completely remove all the HTML from the clone, and I end up with a few input boxes and that's about it. I cannot figure out why.
In this image you can see the first cloned area, and then after pressing the button (with the new find() function added in, as shown above):
Help me Stack Overflow, you're my only hope.
You are missing a .end().
So you were operating on the first selection (input), which means instead of appending the cloned div.duplicate-fields to #duplicate-section, you were instead appending your collection of inputs to #duplicate-section (which explains the five checkboxes)
Try replacing your second block with this
$("div.duplicate-fields:last-child").clone().find('input').each(function () {
this.name = this.name.replace(/\[(\d+)\]/, function (str, p1) { return '[' + (parseInt(p1, 10) + 1) + ']' });
this.value = "";
this.checked = false;
}).end().find("label.button-array.active").each(function () {
$(this).removeClass("active");
}).end().appendTo("#duplicate-section");
Bootply - http://www.bootply.com/bPwHVfFzK8
Try this:
$("div.duplicate-fields:last-child").clone().find('input').each(function() {
this.name = this.name.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
this.value = "";
this.checked = false;
$(this).parent("label.button-array.active").removeClass("active");
}).removeClass("active").end().appendTo("#duplicate-section");
Since you are already looping each input element, you can try to use $.parent() to get the label, then edit its class.
Something like
$("div.duplicate-fields:last-child").clone().find('input').each(function() {
this.name = this.name.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
this.value = "";
this.checked = false;
$(this).parent().removeClass("active");
}).end().appendTo("#duplicate-section");