I assume this is a common problem, but I haven't been able to find the answer in other threads.
The basic idea / goal here is that if a task is marked as important, it gets added to quadrant1. If it isn't, it gets added to quadrant2. When tasks are completed, they can be closed out by clicking on them.
HTML:
I have a simple page with:
A text input (i.e. "task")
Checkbox (i.e. "important")
Submit button (i.e. "submitTask")
Two divs ("quadrant1" and "quadrant2").
JS:
$(document).ready( function () {
$('#submitTask').on("click", function() {
var task = $("#task").val();
var important = $("#important").prop("checked");
var addToQuadrant = function (task, important) {
if (important == true) {
$("#quadrant1").append(
"<p class='taskHolder'> " + task + " </p>");
} else if (important == false) {
$("#quadrant2").append(
"<p class='taskHolder'> " + task + " </p>");
}
});
});
addToQuadrant(task, important);
$('body').on('click', '.taskHolder', function () {
$('.taskHolder').slideUp();
});
});
My problem is that since I use the same id (i.e. "taskHolder") for both paragraph elements, if I add more than one task to my page at a time, I can't remove more than one of them.
My question is: how can I dynamically add an element to the DOM while also giving it a unique id or selector so every task can be uniquely targeted and closed out?
Use:
$(this).slideUp();
instead of
$('.taskHolder').slideUp();
Within the event handler this references the element that the event applied to.
The following is the minimal code I'd use to implement your whole thing:
$(document).ready(function() {
var task = $("#task");
var cb = $("#important");
$("button").click(function() {
$("<p></p>", {
text: task.val(),
"class": "task"
}).appendTo(cb[0].checked ? "#quadrant1" : "#quadrant2");
});
$("body").on("click", ".task", function() {
$(this).slideUp(500, function(){ $(this).remove(); });
});
});
div { border: thin black solid; margin: 4px; min-height: 20px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label>Task: <input id="task"></label>
<label><input type="checkbox" id="important"> Important</label>
<button>Add</button>
<div id="quadrant1"></div>
<div id="quadrant2"></div>
User a global variable 'counter' and increase its value at each click then append this with 'taskHolder'. Now you have unique id for each task.
To select use startwith type selector.
var cnt = 0;
$(document).ready( function () {
$('#submitTask').on("click", function() {
cnt++;
var task = $("#task").val();
var important = $("#important").prop("checked");
var addToQuadrant = function (task, important) {
if (important == true) {
$("#quadrant1").append(
"<p id='taskHolder" + cnt + "' > " + task + " </p>");
} else if (important == false) {
$("#quadrant2").append(
"<p id='taskHolder" + cnt + "'> " + task + " </p>");
};
addToQuadrant(task, important);
$('[id^=taskHolder]').on("click", function() {
$(this).slideUp();
};
});
Alternative solution
A better solution could be common class to each of the tasks
"<p class='commonClass" + cnt + "'> " + task + " </p>");
and
$('body').on('click', '.taskHolder', function () {
$(this).slideUp();
});
You need to apply the new ID for the each newly added element dynamically.
//New length every time you click
var newLength = $('[id^=taskHolder]').length + 1;
//Apply the new ID
$("#quadrant1").append(
"<p id='taskHolder+newLength+'> New " + newLength + " </p>");
$('#submitButton').click(function(){
//New length every time you click
var newLength = $('[id^=taskHolder]').length + 1;
//Apply the new ID
$("#quadrant1").append(
"<p id='taskHolder+newLength+'> New " + newLength + " </p>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="quadrant1">
<p id="taskHolder_1">New 1</p>
</div>
<button id="submitButton">Button</button>
Use unique id
Target item with $(this) to hide on complete.
$(document).ready( function () {
var addToQuadrant = function (task, important) {
if (important == true) {
var taskid = $("#quadrant1").length + 1;
$("#quadrant1").append(
"<p class='taskHolder' id='task-"+taskid+"'> " + task + " </p>");
} else if (important == false) {
var imptaskid = $("#quadrant2").length + 1;
$("#quadrant2").append(
"<p class='taskHolder' id='imp-task-"+imptaskid+"'> " + task + " </p>");
};
};
$('#submitTask').on("click", function() {
var task = $("#task").val();
var important = $("#important").prop("checked");
addToQuadrant(task, important);
});
$('body').on('click', '.taskHolder', function () {
$( this ).slideUp();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Important Task
<div id="quadrant1" style="border:1px dotted;min-height:20px;margin-bottom: 10px">
</div>
Task
<div id="quadrant2" style="border:1px dotted;min-height:20px;margin-bottom: 10px">
</div>
Task: <input type="text" id="task" />
<input type="checkbox" id="important" /> Important
<input type="button" value="Submit" id="submitTask" />
Related
I am using an ecommerce system where I dont have access to HTML code or anything but I can add custom JS code to alter some things and CSS.
I need to edit the shipping info text which is right to Doba dodania text.
My issue is that the event fires only once and not on every select change event.
Can someone help me why it is firing only once? It was needed to add SetTimeOut too.
Please check the page and console logs here:
https://www.privlacuj.sk/Hacik-Offset-Light-Class-AT-21-cena-za-1ks-d2336_1013278452.htm
My code is:
<script type="text/javascript">
function change_doba_dodania() {
var c757_counter = document.querySelectorAll(".c757").length;
var variant = document.querySelectorAll(".c755.variant").length;
var out_of_stock = document.querySelectorAll(".c757.out-of-stock").length;
console.log(c757_counter);
console.log(variant);
console.log(out_of_stock);
if (out_of_stock > 0) {
console.log("Nincs raktaron");
}
if ( ( c757_counter >= 2 ) && ( out_of_stock == 0 ) ){
var dd_text = document.getElementsByClassName("c757")[1].innerHTML;
console.log(dd_text);
var dd_text_array = dd_text.split(" ");
var dd_final = dd_text_array.filter(String);
console.log(dd_final);
if (dd_final[2] == "zajtra") {
document.getElementsByClassName("c757")[1].innerHTML = dd_final[6] + " " + dd_final[7] + " " + dd_final[8] + " " + dd_final[9] + " " + dd_final[10] + " a Vaša zásielka bude expedovaná už " + dd_final[2];
} else {
document.getElementsByClassName("c757")[1].innerHTML = dd_final[6] + " " + dd_final[7] + " " + dd_final[8] + " - " + dd_final[9] + " a Vaša zásielka bude expedovaná už " + dd_final[2];
}
}
}
window.addEventListener('DOMContentLoaded', (event) => {
change_doba_dodania();
});
var variant = document.querySelectorAll(".c755.variant").length;
if (variant > 0){
document.querySelector('.c757 select').addEventListener('change', function()
{setTimeout(change_doba_dodania, 1500)});
document.querySelector('.c757 select').addEventListener('change',() =>
setTimeout(console.log, 1000, "Changed")
)
}
If i got your question, your problem is querySelector.
querySelector only selects the first element with the given class name. If you want to select all the elements with the given class name, you should use querySelectorAll.
document.querySelectorAll(".c757 select").forEach(select => {
select.addEventListener(...)
})
I have a function that Creates new items and allows you to Delete, Update and Save the inputs on these items using localStorage
However, if I have more than one item and then update and save the changes, those changes are applied over all items.
The problem is encountered at the $(".save").click(function() but I'm not sure I have set up my .items with a proper array.
Since I use localStorage the working code can be found in the pen below:
https://codepen.io/moofawsaw/pen/NoBQKV
window.localStorage.clear();
//create localStorage item
if (!localStorage.getItem("_storage")) {
localStorage.setItem("_storage", "");
}
//set data to localStorage function
function saveData() {
localStorage.setItem("_storage", $("#content").html());
}
// Open the create dialgoue:
$(".add").on("click", function() {
$(".create").toggle();
});
//Save the entered inputs and post the item:
$(".post").click(function() {
var id = $(".createtext").val();
var createtitle = $(".createtitle").val();
var item = "";
if (id[0]) {
for (var i = 0; i < id.length; i++) {
item += "<div>" + id[i] + "</div>";
}
} else {
item = "<div>Click update to add a card</div>";
}
$("#content").append(
'<div class="item">' +
'<div class="title">' +
createtitle +
"</div>" +
"<div class='text'>" +
id +
"</div>" +
'<button class="delete">Delete</button>' +
'<button class="update">Update</button>' +
"</div>"
);
$(".createtitle").val("");
$(".createtext").val("");
$(".create").toggle();
saveData();
});
//Close out of creating a new item
$(".close").click(function() {
$(".createtitle").val("");
$(".createtext").val("");
$(".create").toggle();
});
//Get inputs and open edit window to update the items:
$("#content").on("click", ".update", function() {
var item = $(this).closest(".item");
$(".updatetext").val(
$(this)
.closest(".item")
.find(".text")
.text()
);
$(".updatetitle").val(
$(this)
.closest(".item")
.find(".title")
.text()
);
$(".edit").toggle();
});
//Save changes and update the items (error:changes all items when clicked):
$(".save").click(function() {
var id = $(".updatetext").val();
var title = $(".updatetitle").val();
var item = "";
if (id[0]) {
for (var i = 0; i < id.length; i++) {
item += "<div>" + id[i] + "</div>";
}
} else {
item = "<p>Click edit to add a card</p>";
}
$(".item").each(function() {
$(this).html(
'<div class="title">' +
title +
"</div>" +
"<div class='text'>" +
id +
"</div>" +
'<button class="delete">Deleted(2)</button>' +
'<button class="update">Updated(2)</button>'
);
});
$(".updatetext").val("");
$(".updatetitle").val("");
$(".edit").toggle();
saveData();
});
//Discard any of these changes:
$(".discard").click(function() {
$(".updatetext").val("");
$(".updatetitle").val("");
$(".edit").toggle();
});
//Delete an item:
$("#content").on("click", ".delete", function() {
$(this)
.closest(".item")
.remove();
saveData();
});
$(function() {
if (localStorage.getItem("_storage")) {
$("#content").html(localStorage.getItem("_storage"));
}
});
Point is, you call .each() in your update callback.
$(".item").each(function() {
$(this).html(
'<div class="title"> ....'
);
});
This literally means "Find all DOM elements with item class and replace their contents with given html.
But you need to replace contents of the one specific element, on which Update button was clicked. To do so, you need to persist that element somehow.
One of the ways to do that with minimum changes to your code - introduce a variable in a scope available for both update and save functions. But in your case it would be a global variable, and those are not generally a good idea.
So I'd suggest to wrap all your code into a function (like $(function() {});.
Then you can introduce a local variable:
$(function () {
// define it
var $selectedItem;
// assign a value in the update click callback
$('#content').on('click', '.update', function () {
$selectedItem = $(this).closest('.item');
// ...
});
// read the value in the save click callback
$('.save').click(function () {
// ...
$selectedItem.html('...');
// ...
});
});
Example: https://codepen.io/anon/pen/GzXaoV
function demo(){
$('.box').slideToggle('fast');
}
$(document).ready(function(){
$.getJSON( "js/JobOpenings.json", function( data ) {
var glrScrlImg = [];
$.each( data.getJobOpeningsResult, function( key, val ) {
var st = "",id,st2= "",st3="",id;
st +="<h4>" + val.JobTitle + "</h4>";
st3 += "<div class='box'>" + val.JobDetails + "</div>";
$("#newsDetails").append("<li onclick='demo()'>" + st+val.JobSector + "<br>" + st3 + "</li>");
$('.box').hide();
});
});
});
I am reading data from a json file. The div with 'box' class is hidden. Currently this code is displaying all div on click of the li. What changes should I make to display only the div corresponding to the clicked li?
Here what we need to do is to find the .box element within the clicked li, so we need to get a reference to the clicked element.
I would use a delegated jQuery event handler with css to initially hide the element
$(document).ready(function () {
$('#newsDetails').on('click', 'li', function () {
$(this).find('.box').toggleClass('hidden');
})
$.getJSON("js/JobOpenings.json", function (data) {
var glrScrlImg = [];
$.each(data.getJobOpeningsResult, function (key, val) {
var st = "",
id, st2 = "",
st3 = "",
id;
st += "<h4>" + val.JobTitle + "</h4>";
st3 += "<div class='box hidden'>" + val.JobDetails + "</div>";
$("#newsDetails").append("<li>" + st + val.JobSector + "<br>" + st3 + "</li>");
});
});
});
with css
.hidden {
display: none;
}
Pass the control to the function and then based on your control slideToggle its respective .box
function demo(ctrl){
$(ctrl).find('.box').slideToggle('fast');
}
$(document).ready(function(){
$.getJSON( "js/JobOpenings.json", function( data ) {
var glrScrlImg = [];
$.each( data.getJobOpeningsResult, function( key, val ) {
var st = "",id,st2= "",st3="",id;
st +="<h4>" + val.JobTitle + "</h4>";
st3 += "<div class='box'>" + val.JobDetails + "</div>";
$("#newsDetails").append("<li onclick='demo(this)'>" + st+val.JobSector + "<br>" + st3 + "</li>");
$('.box').hide();
});
});
});
Or add a class to li and attach an event handler like below instead of writing inline onclick as below:
$("#newsDetails").append("<li class="someclass"'>" + st+val.JobSector + "<br>" + st3 + "</li>");
and then instead of function demo() write this
$('#newsDetails').on('click','.someclass',function(){
$(this).find('.box').slideToggle('fast');
});
UPDATE
Method 1:
function demo(ctrl){
$('#newsDetails').find('li.box').hide('fast'); //hide all the .box
$(ctrl).find('.box').slideToggle('fast');
}
Method 2:
$('#newsDetails').on('click','.someclass',function(){
$('#newsDetails').find('li.box').hide('fast'); //hide all the .box
$(this).find('.box').slideToggle('fast');
});
UPDATE 2:
Method 1:
function demo(ctrl){
$('#newsDetails').find('li.box').not($(ctrl).find('.box')).hide('fast'); //hide all the .box
$(ctrl).find('.box').slideToggle('fast');
}
Method 2:
$('#newsDetails').on('click','.someclass',function(){
$('#newsDetails').find('li.box').not($(ctrl).find('.box')).hide('fast'); //hide all the .box except this
$(this).find('.box').slideToggle('fast');
});
You should structure your html (which is missing from the question!) so that the div and li are "connected" in some way (maybe the div is child of li, or they have same class, ecc).
Right now the line
$('.box').slideToggle('fast');
is applied to all element with class '.box' in your page. You want to be more selective there, that's where the way you structure the html comes into play.
Here's an example: http://jsfiddle.net/owe0faLs/1/
I am working on a script to add a row to a form using js.
this is the js script I have.
<script>
jQuery(function($) {
var $button = $('#add-row'),
$row = $('.timesheet-row').clone();
$button.click(function() {
$row.clone().insertAfter('#clone-row');
});
});
</script>
Then my form's elements are set up like this.
<div class="form-group col-lg-2">
<label>In Time</label>
<input class="form-control" type="datetime" id="intime" name="intime[]">
</div>
My problem is I cant seem to figure out how to retrieve the values of the form fields
here is the jfiddle
jfiddle
Updated jfiddle to revised code to post to php file
<?php
$pos= $_POST['position'];
$position = json_decode($pos);
echo $position;
echo "This should work";
If anymore than one line is found no response is returned.
Basically you'll need to iterate through the elements to get their values.
.each() will help you in that.
select an element input or select with their name and call .each() on it.
In .each() fetch the value of current element and store it.
Here's the updated jsFiddle.
I took the liberty of adding a button(id = "get-row-values") on whose click you'll see an alert with all the values of your inputs and selects in .timesheet-row.
Also I removed [] from the names of your inputs and selects.
$("#get-row-values").click(function () {
var position = "";
var unit = "";
var employee = "";
var intime = "";
var outtime = "";
$(".timesheet-row select[name=position]").each(function () {
position += " " + $(this).val();
});
$(".timesheet-row select[name=unit]").each(function () {
unit += " " + $(this).val();
});
$(".timesheet-row select[name=employee]").each(function () {
employee += " " + $(this).val();
});
$(".timesheet-row input[name=intime]").each(function () {
intime += " " + $(this).val();
});
$(".timesheet-row input[name=outtime]").each(function () {
outtime += " " + $(this).val();
});
alert("Positions : " + position + "\nUnits : " + unit + "\nEmployees : " + employee + "\nIntimes : " + intime + "\nOuttimes : " + outtime);
});
I'm trying to limit inserting elements to the page:
<script type="text/javascript">
$(function() {
var i = 1;
//allow only 3 elements
if (i < 4) {
$('#add').click(function() {
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
});
i++;
}
$('.remove').live('click', function() {
$(this).parent('p').remove();
});
});
</script>
But I can still add element a lot more than 4.
You need to check your variable i within your event handler.
$('#add').click(function() {
if(i < 4){
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
i++;
}
});
And you should decrease i within your live() handler.
See a working example : http://jsfiddle.net/CtGgg/
You could count the number of elements already on the page and limit it that way. Personally, I like treating the DOM itself as the canonical representation of user state. If that's important to you, you could do something like the following, even though it's a little less performant:
$('#add').live('click', function (evt) {
if ($('input[type=file]').length < 4) {
$('body').append('<p><input type="file"> Remove</p>');
}
evt.preventDefault();
});