For loop parent binding for dynamic children actions - javascript

I have a situation binding click events to the static parent for dynamically added children which is not working. My original post contained example code which seemed to reproduce the problem but was mistakenly using an id in the dynamic content in stead of the class.
This update more accurately represents the actual implementation however I am unable to reproduce the problem in this example.
<div id="page">
<div id="section-0" class="container">
<span>section 0</span>
<div id="section-actions">
<button class="button action-zero">zero</button>
</div>
</div>
<div id="section-1" class="container">
<span>section 1</span>
<div class="section-actions"></div>
</div>
<div id="section-2" class="container">
<span>section 2</span>
<div class="section-actions"></div>
</div>
<script>
action_array = ['zero', 'one', 'two', 'three'];
section_actions = ['one', 'two', 'three'];
add_section_actions();
bind_actions();
function add_section_actions() {
for (var s = 1; s <= 2; s++) { // for sections 1 and 2
var actions_html = '';
for (var i = 0; i < section_actions.length; i++) { // for all the actions
var action = section_actions[i];
actions_html = actions_html + '<button class="action-' + action + '">' + action + '</button>';
}
$('#section-'+s+' .section-actions').html(actions_html);
}
}
function bind_actions() {
//console.log('bind_actions called');
for (var i = 0; i < action_array.length; i++) {
//console.log(i);
var action = action_array[i];
//console.log('attempting to bind action for '+action);
$('#page').on('click', '.action-' + action, function() {
var this_container = $(this).closest('.container');
var this_container_id = this_container.attr('id');
console.log('this_container_id: ' + this_container_id);
});
}
}
</script>

add the class class="action-'+action+'" to your buttons
actions_html = actions_html + '<button class="action-'+action+'" id="section-2-button-' + action + '">' + action + '</button>';
Demo
action_array = ['zero', 'one', 'two', 'three'];
section_two_actions = ['one', 'two', 'three'];
add_section_two_actions();
bind_actions();
function add_section_two_actions() {
var actions_html = '';
for (var i = 0; i < section_two_actions.length; i++) {
var action = section_two_actions[i];
//console.log('adding section 2 action: '+action);
actions_html = actions_html + '<button class="action-'+action+'" id="section-2-button-' + action + '">' + action + '</button>';
}
$('#section-2-actions').html(actions_html);
}
function bind_actions() {
//console.log('bind_actions called');
for (var i = 0; i < action_array.length; i++) {
//console.log(i);
var action = action_array[i];
//console.log('attempting to bind action for '+action);
$('#page').on('click', '.action-' + action, function() {
var this_container = $(this).closest('.container');
var this_container_id = this_container.attr('id');
console.log('this_container_id: ' + this_container_id);
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
<div id="section-0" class="container">
<span>section 0</span>
<div id="section-0-actions">
<button class="button action-zero">zero</button>
</div>
</div>
<div id="section-1" class="container">
<span>section 1</span>
<div id="section-1-actions">
<button class="button action-one">one</button>
<button class="button action-two">two</button>
<button class="button action-three">three</button>
</div>
</div>
<div id="section-2" class="container">
<span>section 2</span>
<div id="section-2-actions"></div>
</div>
</div>

Related

How to get drag + drop Javascript code to apply to each individual task item, making each list item draggable, rather than items together in block?

My drag and drop code does not apply to each new added list item individually, but instead applies to all the list items in one block. However, the purpose of the drag and drop is to make the list items individually sortable and draggable. Any clue to how to correct the code to apply to each new task/list item that is appended under the 'To Do' list?
var $addButton = $(".btn-primary");
var $removeButton = $(".btn-danger");
var $todoList = $(".uncomplete");
var $doneList = $(".completed");
//Take Text Input and Add <li> to To Do List
$addButton.on("click", function(){
//Creating object Variables
var $sort = $(".sort").val();
var $newTask = $(".newTask").val();
var $taskDescr = $(".taskDescr").val();
var $taskDate = $(".taskDate").val();
// var $category= $(".category").val();
var $category= $("input[type='radio'][name='category']:checked").val();
//var $importance = $("input[type='checkbox'][name='importance']:checked").val();
var $importance = $('<input type="checkbox" name="importance"/>').val();
var $newTaskString = $sort + ", " + $taskDescr + ", " + $newTask + ", " + $taskDate + ", " + $category + ", " + $importance + " ";
var $todoList = $(".uncompleted");
//call append method on $todoList
$todoList.append("<li>" + $newTaskString + "<button><span> Done</span></button><button><span> Remove</span></button></li>").addClass("todo");
//drag and drop array
function allowDrop(e)
{
console.log("allow drop");
e.preventDefault();
}
function drop(e)
{
console.log("drop");
e.preventDefault();
var data = e.dataTransfer.getData("text");
e.target.appendChild(document.querySelector("#" + data));
}
function drag(e)
{
console.log("dragging");
//e.preventDefault();
e.dataTransfer.setData("text", e.target.id);
}
function showAllUsers(){
let allUsersDiv=document.querySelector("#allUsersDiv");
for(var i=0; i < allUsers.length; i++)
{
var newUserDiv=document.createElement("DIV");
newUserDiv.setAttribute("draggable", "true");
newUserDiv.setAttribute("ondragstart", "drag(event)"); //"editUser(this)"
newUserDiv.setAttribute("id", ("userdiv-" + i));
newUserDiv.setAttribute("style", "border:1px solid red;");
var newUserEditLink = document.createElement("A");
newUSerEditLink.setAttribute("href", "#");
newUSerEditLink.setAttribute("onclick", "editUSer(this)");
newUserEditLink.innerHTML = "Edit";
newUserEditLink.setAttribute("id", ("edit-", + i));
newUserDiv.innerHTML=allUsers[i].username;
newUserDiv.appendChild(nowUserEditLink);
allUsersDiv.appendChild(newUserDiv);
}
}
<div class="list-wrap" contenteditable="false">
<div class="list-inner-wrap">
<h2 class="title">ToDo List</h2>
<h3 class="title">Add Task</h2>
<!--<h4>Task Name</h4>-->
<label for="sort">Sort Order:</label><input type="text" class="sort"
name="sort" id="sort" value="" placeholder="A,B,C,etc.">
<br> </div></div>
<button class="btn btn-primary">
<span class="glyphicon glyphicon-plus"> Add</span>
</button>
<h3 class="title">To Do</h2>
<h6><i>Click task item to edit or modify</i></h6>
<!--Change color of editable task -->
<div id='div' contenteditable='false' oninput='change()'>
<div id="allUsersDiv" ondragover="allowDrop(event)" ondrop="drop(event)" style="position:absolute;left:5px;top:450px;height:200px;width:500px; border: 1px solid black">
<div draggable="true" ondragstart="drag(event)">
<ul class="uncompleted" contenteditable="false" id="id01" >
<li>Need to be completed task
<button class="btn btn-success">
<span class="glyphicon glyphicon-ok"> Done</span>
</button>
<button class="btn btn-danger">
<span class="glyphicon glyphicon-remove"> Remove</span></button>
<br>
</li></ul>
</div></div></div>

Why does the page refresh when I click on a historical search for the first time?

New coder here,
I'm creating a weather dashboard that keeps a history of each city after you search it. I should be able to click on a city I have previously searched and have it "re-search" that city and give me the expected results. But for some reason when I click on a city I have previously searched, it reloads the page instead. However, cnce the page is reloaded the buttons to search a previous entry work as expected but I can't figure out how to just make the button work--rather than reload and THEN work. (I already tried using event.preventDefault())
Thanks for your help!
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<link rel="stylesheet" href="style.css">
<title>Weather Dashboard</title>
</head>
<body>
<nav class="navbar navbar-dark bg-dark">
<span class="navbar-brand mb-0 h1 w-100 text-center">Weather Dashboard</span>
</nav>
<div class="container">
<div class="row">
<div class="col-4 bg-light">
<p class="search-header my-1">Search for a City</p>
<div class="input-group mb-3">
<input id="city-input" type="text" class="form-control" placeholder="Enter city name" aria-label="Enter city name">
<div class="input-group-append">
<button class="btn btn-primary" type="button" id="search-button">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<button class="btn btn-primary mb-3" type="button" id="clear-history">Clear history</button>
<!-- Add Search History -->
<form id="history"></form>
</div>
<div class="col-8">
<div class="row mr-0">
<div class="col-12 border border-dark m-3 rounded">
<div class="row">
<div class="col-12">
<span id="city-name" class="city-name align-middle"></span>
<img id="weather-icon">
</div>
</div>
<div class="row">
<div class="col-12">
<p id="temperature"></p>
</div>
</div>
<div class="row">
<div class="col-12">
<p id="humidity"></p>
</div>
</div>
<div class="row">
<div class="col-12">
<p id="wind-speed"></p>
</div>
</div>
<div class="row">
<div class="col-12 d-flex">
<div id="UV-index"><span id="UV-val"></span></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h3>5-Day Forecast</h3>
</div>
</div>
<!-- This is where the 5 day forecast is appended -->
<div id="add-forecast" class="row">
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>
JAVASCRIPT
$(document).ready(function(){
var APIKey = API;
var cityName;
$("#search-button").on("click", function(event) {
event.preventDefault();
event.stopPropagation();
cityName = $("#city-input").val();
if (cityName !== "") {
renderWeather();
renderForecast();
autoSaveHistory();
};
});
function renderWeather() {
var queryURL = "http://api.openweathermap.org/data/2.5/weather?q=" + cityName + "&appid=" + APIKey
$.ajax({
url : queryURL,
method : "GET"
}).then(function(response){
// console.log(queryURL);
// console.log(response);
var cityName = response.name;
var icon = response.weather[0].icon;
var iconURL = "https://openweathermap.org/img/wn/" + icon + ".png"
var temp = response.main.temp;
var humidity = response.main.humidity;
var windSpeed = response.wind.speed;
var lat = response.coord.lat;
var lon = response.coord.lon;
var uvQuery = "http://api.openweathermap.org/data/2.5/uvi?lat=" + lat + "&lon=" + lon + "&appid=" + APIKey
// UV Index API
$.ajax({
url : uvQuery,
method : "GET"
}).then(function(response){
var UV = response.value;
UV = Number(UV);
if (UV >= 8) {
$("#UV-val").addClass("danger-zone");
} else {
$("#UV-val").removeClass("danger-zone");
$("#UV-val").addClass("safe-zone");
};
$("#UV-val").text("UV Index: " + UV);
});
temp = Number(temp)
temp = (Math.round((temp - 273.15) * 9/5 + 32))
$("#city-name").text(cityName + " " + (moment().format("(MM/DD/YY)")));
$("#weather-icon").attr("src", iconURL);
$("#temperature").text("Temperature: " + temp + " \u00B0F");
$("#humidity").text("Humidity: " + humidity + "%");
$("#wind-speed").text("Wind Speed: " + windSpeed + " MPH");
});
};
function renderForecast() {
var fiveDayQuery = "http://api.openweathermap.org/data/2.5/forecast?q=" + cityName + "&appid=" + APIKey
$.ajax({
url : fiveDayQuery,
method : "GET"
}).then(function(response){
// console.log(response);
$("#add-forecast").text("");
var days = 0;
for (var i = 4; i < 37; i+=8) {
var forecast = $("<div>");
forecast.addClass("col forecast bg-primary text-white ml-3 mb-3 rounded");
var dateP = $("<p>");
var iconP = $("<img>");
var tempP = $("<p>");
var humidityP = $("<p>");
var forecastTemp = response.list[i].main.temp;
forecastTemp = Number(forecastTemp)
forecastTemp = (Math.round((forecastTemp - 273.15) * 9/5 + 32));
var forecastHumidity = response.list[i].main.humidity;
var forecastIcon = response.list[i].weather[0].icon;
var forecastIconURL = "https://openweathermap.org/img/wn/" + forecastIcon + ".png"
days++;
dateP.text(moment().add(days, 'days').format('MM/DD/YY'));
dateP.css("font-size", "20px");
forecast.append(dateP);
iconP.attr("src", forecastIconURL);
forecast.append(iconP);
tempP.text("Temp: " + forecastTemp + " \u00B0F");
forecast.append(tempP);
humidityP.text("Humidity: " + forecastHumidity + "%");
forecast.append(humidityP);
$("#add-forecast").append(forecast);
};
});
};
var searchHistory = {
"cityName": []
};
var pullHistory = JSON.parse(localStorage.getItem("search"));
if (localStorage.getItem("search") !== "undefined") {
setHistory();
}
function setHistory() {
for (var m = 0; m < pullHistory.cityName.length; m++){
console.log("test", pullHistory.cityName[m]);
searchHistory.cityName.push(pullHistory.cityName[m]);
localStorage.setItem("search", JSON.stringify(searchHistory));
}
addHistoryItems();
};
function addHistoryItems() {
$("#history").text("");
pullHistory = JSON.parse(localStorage.getItem("search"));
for (var k = 0; k < pullHistory.cityName.length; k++) {
var cityName = pullHistory.cityName[k];
var searchItem = $("<div>");
searchItem.addClass("row");
var searchButton = $("<button>");
searchButton.attr("index-name", cityName);
searchButton.addClass("history-btn");
searchButton.text(cityName);
searchButton.addClass("btn btn-primary btn-lg");
searchButton.css({"text-transform" : "capitalize" , "margin" : "5px"});
searchItem.append(searchButton);
$("#history").append(searchItem);
};
};
function autoSaveHistory() {
searchHistory.cityName.push(cityName);
localStorage.setItem("search", JSON.stringify(searchHistory));
addHistoryItems();
}
$(".history-btn").on("click", function(event) {
event.preventDefault();
console.log("checked")
cityName = $(this).attr("index-name");
renderWeather();
renderForecast();
});
$("#clear-history").on("click", function(event) {
event.preventDefault();
localStorage.clear();
$("#history").text("");
searchHistory = {
"cityName": []
};
localStorage.setItem("search", JSON.stringify(searchHistory));
});
});
because when click city item, it trigger <form id="history"></form> default behavior : form submit .
so, event.preventDefault() need in form summit handler , not button click handler , like this:
$('form#history').submit((event) => {
event.preventDefault();
// ....
})
BTW, for jquery, return false has the same effect .

array does not fetch the data in HTML?

I'm trying to make the news list more dynamic , so i tried to make it in array and loop on the categories but unfortunately the function getw () does not fetch the data ?
<nav class="navbar navbar-expand-sm navbar-dark bg-dark mb-5">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId"
aria-controls="collapsibleNavId" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav ml-auto ml-2 mt-lg-0" id="line">
</ul>
</div>
</nav>
<div class="container">
<div class="row" id="posts-row">
</div>
</div>
java script code
var list = ["General", "Entertainment", "Health", "Science", "Sports", "Technology"];
function getw() {
var lines = "";
for (var i = 0; i < list.length; i++) {
lines += `<li>
<a class='nav-link' href='#'>` + list[i] + `</a>
</li>`
}
document.getElementById("line").innerHTML = lines; (not working i don't know why ?)
}
getdata("general")
var links = document.getElementsByClassName("nav-link");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function (e) {
var currentCat = e.target.text;
getdata(currentCat.toLowerCase())
})
}
var data;
function getdata(category) {
var httpReq = new XMLHttpRequest();
httpReq.open("GET", "http://newsapi.org/v2/top-headlines?country=eg&category=" + category + "&apiKey=d4f87946d7fc4322be9c2089316d5625");
httpReq.send();
data = [];
httpReq.addEventListener("readystatechange", function () {
if (httpReq.readyState == 4) {
data = JSON.parse(httpReq.response).articles;
Display();
}
})
}
function Display() {
var temp = "";
for (var i = 0; i < data.length; i++) {
temp += `<div class ='col-md-4'>
<div>
<img src=`+ data[i].urlToImage + ` class='img-fluid'>
<h4>`+ data[i].title + `</h4>
<p>`+ data[i].description + `</p>
</div>
</div>`
}
document.getElementById("posts-row").innerHTML = temp;
}
.............................................................................................///////////////////////////////////////////
At least in the code you posted, you are not invoking the getw function.
Try adding getw() at the end of your JavaScript.

add class in for loop button click

(function ($) {
$.fn.fCycle = function () {
var x;
for (x in arguments) {
$(arguments[x]).close();
}
$(this).collapse("show");
};
$(".btn-next").on('click', function() {
var form = [$("#name"), $("#surname"), $("#student_number"), $("#cellphone"), $("#email"), $("#course"), $("#year")],
i = 0,
a = "#" + $(this).attr("data-to"),
b = "#" + $(this).attr("data-from");
if ($(this).hasClass("to_course")) {
for (i; i < 5; i++) {
console.log(form[i].val());
if (form[i].val() === undefined) {
form[i].addClass("has-danger")
$(a).fCycle(b);
} else if (form[i].hasClass("has-danger") && form[i].length > 0) {
form[i].removeClass("has-danger")
}
}
$(a).fCycle(b);
}
});
}(jquery));
$(".btn-next").on('click', function () {
var form = [$("#name")],
i = 0,
a = "#" + $(this).attr("data-to"),
b = "#" + $(this).attr("data-from");
if ($(this).hasClass("to_course")) {
for (i; i < form.length; i++) {
if (form[i].val() === undefined) {
form[i].addClass("has-danger")
$(a).fCycle(b);
}
else if (form[i].hasClass("has-danger") && form[i].length > 0) {
form[i].removeClass("has-danger");
}
}
$(a).fCycle(b);
}
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet"/>
<form method="post" id="apply">
<div id="personal" class="collapse in">
<fieldset class="col-xs-10 col-xs-offset-1 form-group">
<div class="row">
<label for="names">Name(s)</label>
<input class="form-control" type="text" name="names" id="names" placeholder="Enter your full name here">
</div>
<hr>
<div class="row">
<nav>
<ul class="pager">
<li>
<button class="btn btn-danger btn-cancel" type="button">cancel</button>
</li>
<li class="pager-next">
<button class="btn btn-next btn-success to_course" type="button" data-to="course" data-from="personal">next</button>
</li>
</ul>
</nav>
</div>
</fieldset>
</div>
<div id="course" class="collapse">
<p>course</p>
</div>
</form>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The above snippet doesn't seem to work at all - in the case of the Original (http://alpha.msauwc.co.za -> if you click on the Join the MSA button,
You'll find that the form does work. The issue is that the next button should not be working when the input fields have not been filled.
This has to be prevented using jquery.
Try defining your array with just selector strings, and then wrapping your form[i] objects like:
$(form[i]).val(), $(form[i]).addClass('has-danger'), etc
You can use these methods to disable & activate the button:
$(".btn-next").addClass('disabled') // when you want to disable it
$(".btn-next").removeClass('disabled') // when you want to activate it

Append HTML to row if condition true, make sure there's still 3 columns to a row

I want to add the HTML of a column into a row, and have 3 columns per row. I do not wish to display all of the images in my array, and if they are not supposed to be displayed, I do not wish for the column number to tick over.
This should be really easy, but I'm getting really confused. My current code is just giving me an infinite loop getting stuck on an image where it is not supposed to display.
function loadImages()
{
var data = <?php echo json_encode($data); ?>;
data = $.map(data, function(value, index) {
return [value];
});
console.log(data);
for(var i = 0; i < data.length; i++)
{
data[i] = $.map(data[i], function(value, index) {
return [value];
});
}
var div = document.getElementById('imageBox');
var img = 0;
var row = 0;
while(img < data.length)
{
div.innerHTML += '<div class="row gallery-row" id="row' + row + '"></div>';
var col = 0;
while(SOMETHING OR OTHER)
{
if(!!data[img])
{
var html = [
'<div class="col-sm-4">',
' <a data-toggle="modal" data-target="#imageModal" onclick="" href="#" id=a' + img + '>',
' <img class="img-responsive img-gallery" src="" id=img' + img + '>',
' </a>',
'</div>'
].join('');
var valid = data[img][1][4].split(": ")[1];
if(valid == "True")
{
var imgName = data[img][0];
var name = data[img][1][0];
var location = data[img][1][1];
var desc = data[img][1][2];
document.getElementById('row'+ String(row)).innerHTML += html;
document.getElementById('img' + String(img)).setAttribute('src', imgName);
document.getElementById('a' + String(img)).setAttribute('onclick', "javascript:loadModalImage('" + imgName + "', '" + name + "', '" + location + "', '" + desc + "')");
col++;
}
img++;
}
}
row++;
}
}
function loadImageData(imageName, imageLocation, imageDesc)
{
var imgName = document.getElementById('img-name');
var imgDesc = document.getElementById('img-desc');
imgName.innerHTML = "Taken by <b>" + imageName + "</b> at <b>" + imageLocation + "</b>.<br>";
imgDesc.innerHTML = imageDesc;
}
function loadModalImage(image, imageName, imageLocation, imageDesc)
{
var modalImage = document.getElementById('imageModalImage');
modalImage.setAttribute("src", image);
loadImageData(imageName, imageLocation, imageDesc);
}
And the HTML:
<div class="box" name="box" id="imageBox">
<!-- Modal -->
<div class="modal fade" id="imageModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-img">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
</div>
<!-- Modal Body -->
<div class="modal-body">
<img class="img-responsive imageModalImage" id="imageModalImage" src="">
<p id="img-name"></p>
<p id="img-desc"></p>
</div>
<!-- Modal Footer -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
As I said, I'm sure this should be an easy fix. Any help is still greatly appreciated, as I've just completely confused myself trying to solve this.

Categories

Resources