jquery: read inside each div, span and input - javascript

I'm creating a project in ASP.NET MVC and jQuery. When a user click on addSentence button, I want to duplicate a div called copythis with all events and insert it in another div called myform.
in copythis I have two div: in the first there is a span called sentence where I insert the text in the input in the second the user can add more then one field with different text.
When the user clicks the button called save I want to read all copythis in myform and create a structure to send to a webapi.
I have a problem is the javascript because I can read properly each div.
$("#addSentence").on("click", function (event) {
if ($("#inputSentence").val() == "")
alert("Sentence must have a value");
else {
event.preventDefault();
var theContainer = $("#copythis");
if (theContainer != null) {
var clonedSection = $(theContainer).clone(true);
if (clonedSection != null) {
$(clonedSection).find("#sentence")
.text($("#inputSentence").val());
$(clonedSection).appendTo("#myform");
}
}
}
});
$("#save").on("click", function (event) {
$("#myform #copythis").children().each(function (index, element) {
var elm = $(this);
var sentence = elm.find('.row span#sentence').val();
if (sentence != '') {
console.log('Sentence: ' + sentence);
$("input").children().each(function (m, l) {
var txt = $(this).val();
if (txt != '') {
console.log('Example: ' + txt);
}
});
}
});
});
function makeRepeater(sectionsSelector, addClass, removeClass, AYSMsg) {
$(sectionsSelector + " " + addClass + "," + sectionsSelector +
" " + removeClass).on("click", function (event) {
// Avoiding the link to do the default behavior.
event.preventDefault();
// Get the container to be removed/cloned
var theContainer = $(this).parents(sectionsSelector);
if ($(this).is(addClass)) {
// Cloning the container with events
var clonedSection = $(theContainer).clone(true);
// And appending it just after the current container
$(clonedSection).insertAfter(theContainer);
} else {
// If the user confirm the "Are You Sure" message
// we can remove the current container
if (confirm(AYSMsg)) {
// Making fade out, hide and remove element a sequence
// to provide a nice UX when removing element.
$(theContainer).fadeOut('normal',
function () {
$(this).hide('fast',
function () { $(this).remove(); }
);
}
);
}
}
});
}
makeRepeater(
'.my-repeated-section-form', /* The container selector */
'.addform', /* The add action selector */
'.removeform', /* The remove action selector */
'Are you sure you want to remove this section?' /* The AYS message. */
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="row">
<div class="row">
<div class="col-lg-10">
<div class="input-group">
<input id="inputSentence" type="text"
class="form-control" placeholder="Sentence...">
<span class="input-group-btn">
<button class="btn btn-secondary"
type="button" id="addSentence">Add</button>
</span>
</div>
</div>
</div>
<div class="col-lg-12">
<div style="display: inline;">
<div class="group-of-repeated-sections" style="display: none;">
<div class="my-repeated-section">
<div id="copythis">
<div class="row">
<div class="col-lg-10">
<span id="sentence"></span>
</div>
<div class="col-lg-2">
<span>
+
-
</span>
</div>
</div>
<div class="my-repeated-section-form">
<div class="row">
<div class="col-lg-12">
<input type="text" />
<span>
+
-
</span>
</div>
</div>
</div>
<div style="height:25px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="myform"></div>
<button id="save">Save</button>

Related

How to create elements and delete them with native javascript without using jQuery

In the below link, there is a add more button, i want the add more to create the same input field with a delete button associated with it, but i would like to do it all with native js if possible.
https://codepen.io/aazim-khaki/pen/vYZmMRq
Current JS :
$(function() {
$(".btn-copy").on('click', function() {
var ele = $(this).closest('.example-2').clone(true);
ele.find('input').val('')
if (ele.find('button').length < 2) {
let btn = document.createElement("button");
btn.innerHTML = "Delete";
btn.onclick = (e) => {
e.preventDefault()
ele.remove()
}
ele[0].appendChild(btn);
}
$(this).closest('.example-2').after(ele);
})
})
Delegate
I moved the form tag and gave the button a delete class
window.addEventListener("load", function() {
document.querySelector(".row").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains('delete')) {
tgt.closest('.example-2').remove()
} else if (tgt.classList.contains('btn-copy')) {
const ele = tgt.closest(".example-2").cloneNode(true);
ele.querySelector("input").value = "";
if (ele.querySelectorAll("button").length < 2) {
let btn = document.createElement("button");
btn.innerHTML = "Delete";
btn.classList.add("delete");
ele.appendChild(btn);
}
tgt.closest(".card-body").appendChild(ele)
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Add Class</h5>
</div>
<form action="#">
<div class="card-body">
<div class="example-2 form-group row">
<!--<label class="col-form-label col-md-2">Input Addons</label>-->
<div class="col-xs-2">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Class Name</span>
</div>
<input class="form-control" type="text">
<div class="input-group-append">
<button class="btn-copy btn btn-primary" type="button">Add More</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-xs-2">
<button class="btn btn-primary" type="button">Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
Use a container and event delegation so you only use one listener rather than attaching a listener to each remove button.
This is a very simple example but the principles are the same.
// Cache your elements
const container = document.querySelector('#container');
const add = document.querySelector('button');
// Add your container an add button listeners
container.addEventListener('click', handleEvent, false);
add.addEventListener('click', handleAdd(), false);
// If a remove button is clicked, find the
// the closest div wrapper and remove it from
// the container
function handleEvent(e) {
const { id } = e.target.dataset;
const row = e.target.closest('.row');
container.removeChild(row);
}
// `handleAdd` returns a function (closure) that
// is used for the add listener rather than
// maintaining a global variable.
// We initialise the id at this point
function handleAdd(id = 0) {
// And now return the function that will be called
// when the add button is clicked
// For the purposes of this example it simply adds new HTML
// to the container, and then increases the id
return function() {
const html = `<div class="row"><input value="${id}" /><button data-id="${id}">Remove</button></div>`;
container.insertAdjacentHTML('beforeend', html);
++id;
}
}
<button>Add</button>
<div id="container"></div>

Displaying elements based on search

I would like the .box elements to show/hide based on the words the user searches for, so for example if a user types in 'Title2 Title1' because those words exists inside box one and two they will remain visible with the renaming .box elements hiding. All the text within the .box elements needs to be searchable not just that in the .title element.
Below is how far I've got. It's almost there but it's not quite working as hoped.
Any help would be great.
Many thanks.
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">
Box title one content
</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">
Box title two content
</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">
Box title three content
</div>
</div>
<script>
$("#search").on("input", function () {
var search = $(this).val();
if (search !== "") {
var searchArray = search.split(" ");
searchArray.forEach(function(searchWord) {
$(".box").each(function () {
if($(this).is(':contains('+ searchWord +')')) {
$(this).show();
} else {
$(this).hide();
}
});
});
} else {
$(".box").show();
}
});
</script>
You need to use a different search method. :contains does not work as you expect. Consider the following example.
$(function() {
function filter(e) {
var term = $(e.target).val();
if (term.length < 3) {
$(".box").show();
return;
}
$(".box").each(function(i, el) {
if ($(".content", el).text().indexOf(term) >= 0) {
$(el).show();
} else {
$(el).hide();
}
});
}
$("#search").keyup(filter);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">Box title one content</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">Box title two content</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">Box title three content</div>
</div>
So for example if on is entered, no filtering is performed. If one is entered, the script will look inside the content class of each box and if one is found in the text, it will be shown otherwise, it is hidden. If the User clears their search out, all items are shown.
Hide all box before iterate, then only show when match any words:
$("#search").on("input", function () {
var search = $(this).val();
if (search !== "") {
var searchArray = search.split(" ");
// Hide all .box
$(".box").each(function () {
$(this).hide();
})
searchArray.forEach(function(searchWord) {
$(".box").each(function () {
if($(this).is(':contains('+ searchWord +')') ) {
$(this).show();
}
});
});
} else {
$(".box").show();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">
Box title one content
</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">
Box title two content
</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">
Box title three content
</div>
</div>
Loop through all .boxs and using regex pattern matching, check either the title or content matches the search query. Show all matched boxes and hide all others
I have also fiddled it here
$("#search").on("input", function () {
var searchables=$('.box');
console.log(searchables)
var query=$(this).val();
searchables.each(function(i,item){
var title=$(item).find('.title').text();
var content=$(item).find('.content').text();
var rgx=new RegExp(query,'gi');
if(rgx.test(title) || rgx.test(content))
{
$(item).show();
}
else
{
$(item).hide();
}
})
})

Note taking feature, line break and no content

I'm building the feature to take notes on my web app. I'm running into two problems:
I can't figure out how to recognize line breaks. I can hardcore text with line breaks, but when user clicks Edit it shows on the text the <br> and if he saves it just shows <br> in plain text.
Also if the user deletes all the text and clicks save it doesn't work and just prints <textarea>.
Any help is greatly appreciated!
$('#edit').click(function() {
$('#edit').hide();
$('#note').each(function() {
var content = $(this).html();
$(this).html('<textarea style="width:inherit">' + content + '</textarea>');
});
$('#save').show();
});
$('#save').click(function() {
$('#save').hide();
$('textarea').each(function() {
var content = $(this).val(); //.replace(/\n/g,"<br>");
$(this).html(content);
$(this).contents().unwrap();
});
$('#edit').show();
});
#note {
word-wrap: break-word;
max-width: 40rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-6">
<h5 class="card-tittle">Note</h5>
<hr>
<div class="container index">
<div class="row">
<div class="jumbotron col-md-12" id="note">
Test Text.
</div>
<div class="col-md-12">
<button class="btn btn-primary" id="edit"><span class="glyphicon glyphicon-edit"></span>Edit</button>
<button class="btn btn-primary" id="save"><span class="glyphicon glyphicon-save"></span>Save</button>
</div>
</div>
</div>
</div>
I think you want to do something like this...
$('#edit').click(function() {
$('#edit').hide();
$('#note').each(function() {
var content = $(this).html().replace(/<br>/g,"\n");
$(this).html('<textarea style="width:inherit">' + content + '</textarea>');
});
$('#save').show();
});
$('#save').click(function() {
$('#save').hide();
$('textarea').each(function() {
var content = $(this).val().replace(/\n/g,"<br>"); //.replace(/\n/g,"<br>");
$(this).html("");
$(this).append(content);
$(this).contents().unwrap();
});
$('#edit').show();
});
Demo: https://www.codeply.com/go/hAL9pWWUFk

able to Select and deselect multiple elements in html and keep track of what has been selected

My HTML template will be appended many times depending upon the backend. So, I want to select the topics and send the id of selected elements. How to do it?
Right now I can only select and also after that i can't de-select it too.
Help!!
My Jquery code to select:
$(document.body).click(function(evt){
var clicked = evt.target;
var currentID = clicked.id || "No ID!";
document.getElementById(currentID).style.backgroundColor = "#00afbc";
//$(clicked).html(currentID);
})
My Html code:
<div class="container-fluid" id="container-<%=no%>">
<div id="circle" style="background:<%= colorCode %>;" class="col-xs-3">
<div class="text" style="color:<%= textColor %>;">
<%=p ercent %>
</div>
<div class="percent" style="color:<%= textColor %>;">%</div>
</div>
<div id="sideText">
<div class="checkbox col-xs-9 everything-checkbox">
<!--input type="checkbox" class="toggle" /-->
<div id="currentID">
<%=currentID %>
</div>
<div id="question">
<%=t otalQues %> Questions Attempts
</div>
</div>
</div>
</div>
<hr style="width: 100%; color: #d9d9d9; height: 1px; background-color:#d9d9d9; margin-top:0px;margin-bottom:0px;" />
You can just add and remove a class to keep track of the selected items and then just get all the selected items with an ID
$(document).ready(function () {
$(document.body).click(function (evt) {
var clicked = evt.target;
if (!$(clicked).hasClass('selected')) {
$(clicked).addClass('selected');
$(clicked).css('background-color', '#00afbc');
} else {
$(clicked).removeClass('selected');
$(clicked).css('background-color', '');
}
});
});
function getSelected() {
var ids = [];
$('.selected').each(function () {
var id = $(this).attr('id');
if (id) {
ids.push($(this).attr('id'));
}
});
return ids;
}

How do I make JS code not affect other DIV?

Hi I am try to make a list of item, I have "add" and "minus" button for each item. The problem is that the JS code I had control two items together. ex. if I click "add" for item1, then the item2 gets added as well.
Looks like that my JS functions works for all button elements. So when I click a "button" element, all buttons get triggered.
How can I do add them individually?
PS: I guess I need to do something like a specific ID for JS to trigger. My thought is add a unique ITEM ID for each one and trigger the button under that specific ID so other buttons under other ITEM ID don't get triggered.
Here is my HTML code:
<div class="row bb">
<div class="col-xs-12 food-container">
<img src="img/1.png" class="min-w img-responsive" />
<div class="food-detail">
<div class="food-name">test</div>
<div class="food-sales">test:233333</div>
<div class="food-price">
¥50
<div class="food-edit">
<button class="btn btn-info" value="50.55" id="minus">-</button>
<span class="num-sales"></span>
<button class="btn btn-info" value="50.55" id="add">+</button>
</div>
</div>
</div>
</div>
</div>
<div class="row bb">
<div class="col-xs-12 food-container">
<img src="img/1.png" class="min-w img-responsive" />
<div class="food-detail">
<div class="food-name">test</div>
<div class="food-sales">test:233333</div>
<div class="food-price">
¥50
<div class="food-edit">
<button class="btn btn-info" value="50.55" id="minus">-</button>
<span class="num-sales"></span>
<button class="btn btn-info" value="50.55" id="add">+</button>
</div>
</div>
</div>
</div>
</div>
Here is my JS:
var theTotal = 0;
var theSales = 0;
var minusButton = document.getElementById('minus');
if (theSales == 0) {
$(minusButton).hide();
}
$('button').click(function () {
var ID = this.id;
if (ID == "add") {
$(minusButton).show();
theTotal = Number(theTotal) + Number($(this).val());
theSales++;
var num = theTotal.toFixed(2);
$('.total').text("¥" + num);
$('.total-num-of-sales').text(theSales + "份");
$('.num-sales').text(theSales);
};
if (ID == "minus") {
theTotal = Number(theTotal) - Number($(this).val());
theSales--;
var num = theTotal.toFixed(2);
if ( theSales == 0 ) {
$('.total').text("");
$('.total-num-of-sales').text("");
$('.num-sales').text("");
$(minusButton).hide();
}
else if ( theSales > 0 ) {
$('.total').text("¥"+num);
$('.total-num-of-sales').text(theSales + "份");
$('.num-sales').text(theSales);
}
};
});
Don't use multiple id on same page
http://jsfiddle.net/bjc1c9tr/4/
Check this will help you
var theTotal = 0;
var theSales = 0;
var minusButton = $('.minus');
if (theSales == 0) {
$(minusButton).hide();
}
$('button').click(function(){
var ID = $(this).attr('data');
if (ID == "add") {
$(this).parent().find('.minus').show();
theTotal = Number($(this).parent().find('.num-sales').text()) + Number($(this).val());
theSales = Number($(this).parent().find('.num-sales').text()) + Number(1);
var num=theTotal.toFixed(2);
$(this).parent().find('.total').text("¥"+num);
$(this).parent().find('.total-num-of-sales').text(theSales+"份");
$(this).parent().find('.num-sales').text(theSales);
};
if (ID == "minus") {
theTotal = Number($(this).parent().find('.num-sales').text()) - Number($(this).val());
theSales= Number($(this).parent().find('.num-sales').text()) - Number(1);
var num=theTotal.toFixed(2);
if ( theSales == 0) {
$('.total').text("");
$(this).parent().find('.total-num-of-sales').text("");
$(this).parent().find('.num-sales').text("");
$(this).parent().find('.minus').hide();
}
else if ( theSales > 0) {
$(this).parent().find('.total').text("¥"+num);
$(this).parent().find('.total-num-of-sales').text(theSales + "份")
$(this).parent().find('.num-sales').text(theSales);
}
};
});
html (added new classes)
<div class="row bb">
<div class="col-xs-12 food-container">
<img src="img/1.png" class="min-w img-responsive" />
<div class="food-detail">
<div class="food-name">test</div>
<div class="food-sales">test:233333</div>
<div class="food-price">¥50
<div class="food-edit">
<button class="btn btn-info minus" value="50.55" data="minus">-</button>
<span class="num-sales"></span>
<button class="btn btn-info add" value="50.55" data="add">+</button>
</div>
</div>
</div>
</div>
</div>
<div class="row bb">
<div class="col-xs-12 food-container">
<img src="img/1.png" class="min-w img-responsive" />
<div class="food-detail">
<div class="food-name">test</div>
<div class="food-sales">test:233333</div>
<div class="food-price">¥50
<div class="food-edit">
<button class="btn btn-info minus" value="50.55" data="minus">-</button>
<span class="num-sales"></span>
<button class="btn btn-info add" value="50.55" data="add">+</button>
</div>
</div>
</div>
</div>
</div>
$('button').click(function(){
var ID = this.id;
if (ID == "add") {
$(minusButton).show();
theTotal = Number(theTotal) + Number($(this).val());
theSales = Number($(this).parent().find('.num-sales').text())+1;
var num=theTotal.toFixed(2);
$('.total').text("¥"+num);
$('.total-num-of-sales').text(theSales+"份");
$(this).parent().find('.num-sales').text(theSales);
};
if (ID == "minus") {
theTotal = Number(theTotal) - Number($(this).val());
theSales = Number($(this).parent().find('.num-sales').text())-1;
var num=theTotal.toFixed(2);
if ( theSales == 0) {
$('.total').text("");
$('.total-num-of-sales').text("");
$(this).parent().find('.num-sales').text("");
//$('.num-sales').text("");
$(minusButton).hide();
}
else if ( theSales > 0) {
$('.total').text("¥"+num);
$('.total-num-of-sales').text(theSales + "份");
$(this).parent().find('.num-sales').text(theSales);
//$('.num-sales').text(theSales);
}
};
$(this).parent().find('.num-sales').text(theSales);
By this way you can get the parent of clicked button and change the value of .num-sales of the selected parent
https://jsfiddle.net/s2u9eb36/ refer this one
You are mixing the elements because of your id and class selectors.
When you select elements through jQuery by class (like $('.num-sales')), jQuery gives you a collection of all elements that match the selector. In your case, that would be both class="num-sales" elements.
Whenever you then call a function (like .html(theSales)), it will apply that function to each element in the collection, that's why your code is affecting more than one element.
You will need to find a way to distinguish one element of the other. There's quite a few options here, but I like doing it by limiting the scope of my selectors. With this I mean I would first find the food-detail div that contains the clicked element, and then find .num-sales etc... only within that element.
Then you can do the following in your button clicks:
$('button').click(function(){
var ID = this.id;
var element = $(this) //make a jQuery object of the clicked button
// finds the first parent element with class food-detail
var container = element.closest('.food-detail');
// find .num-sales within container
var numSales = container.find('.num-sales')
// continue...
});
in short:
when a button is clicked, find the food-detail div the button is in
.find in only that container instead of using selectors on the entire document
Edit: you should really change the id="Add" and id="minus" on your buttons, ids should be unique on the entire document. You can simply add add or minus as a class instead and check for it with element.hasClass('add').

Categories