converting .live() to .on() or .click() functions jquery - javascript

I'm currently following a tutorial that uses an old version of jQuery to create an mvc with a built in todo list using ajax calls. The original code went as follows:
$(function() {
$.get('dashboard/xhrGetListings', function(o) {
for (var i = 0; i < o.length; i++)
{
$('#listInserts').append('<div>' + o[i].text + '<a class="del" rel="'+o[i].id+'" href="#">X</a></div>');
}
$('.del').live('click', function() {
delItem = $(this);
var id = $(this).attr('rel');
$.post('dashboard/xhrDeleteListing', {'id': id}, function(o) {
delItem.parent().remove();
}, 'json');
return false;
});
}, 'json');
$('#randomInsert').submit(function() {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function(o) {
$('#listInserts').append('<div>' + o.text + '<a class="del" rel="'+ o.id +'" href="#">X</a></div>');
}, 'json');
return false;
});
});
When I updated the jQuery version it threw a hissy fit and wouldn't work so I looked up the error and it didn't like up the .live() function and so a suggestion was to use .on()
And so I changed the .live into
$(document).on("click", ".del", function()
Now the code does delete from the database but doesn't update until the page is refreshed . . . am I missing something?

You are binding the event to the document. So you do not need to do this more than once, and the elements in question do not need to be present when you bind the event. Move the on syntax outside of the ajax callback, inside the document ready.
$(function(){
$('#listInserts').on("click", ".del", function() {
});
})
Other option is to leave it inside the callback, and modify your code to be:
$.get('dashboard/xhrGetListings', function(o) {
$('.del').on('click',function(){
});
});
NOTE: As suggested below in the comment, the first option would be more suitable in this case since the .del elements are added in the subtmit, unless you want to bind the click event from there as well.

Here's how I would re-write the sample code. I've commented where I changed things.
$(function() {
var $listInserts = $('#listInserts'); // Store the element once so we don't have to do it again
// Function for re-usability
function addToList (text, id) {
$listInserts.append('<div>' + text + '<a class="del" rel="'+id+'" href="#">X</a></div>');
}
// Here I'm assuming that $('#listInserts') is a container for all those .del elements.
// If you use .on() on a containing element try to keep as close to those elements as you can.
// Keeping it close keeps the events from having to bubble up through every parent element on the page.
$listInserts.on('click', '.del', function(e) {
var $delItem = $(this);
e.preventDefault(); // Stops the normal link behavior. Sort of like 'return false;' would do.
$.post('dashboard/xhrDeleteListing', {'id': this.id}, function(o) {
$delItem.parent().remove();
}, 'json');
});
$.get('dashboard/xhrGetListings', function(o) {
for (var i = 0; i < o.length; i++)
{
addToList(o[i].text, o[i].id);
}
}, 'json');
// Changed to .on()
$('#randomInsert').on('submit', function(e) {
var url = $(this).attr('action');
var data = $(this).serialize();
e.preventDefault();
$.post(url, data, function(o) {
addToList(o.text, o.id);
}, 'json');
return false;
});
});

Move event handler for .del outside callback function
Change to reuse cached delItem
Remove delItem from global scope
Modified code:
$(document).ready(function () {
$(document).on("click", ".del", function () {
var delItem = $(this);
var id = delItem.attr('rel');
$.post('dashboard/xhrDeleteListing', {
'id': id
}, function (o) {
delItem.parent().remove();
}, 'json');
});
$.get('dashboard/xhrGetListings', function (o) {
for (var i = 0; i < o.length; i++) {
$('#listInserts').append('<div>' + o[i].text + '<a class="del" rel="' + o[i].id + '" href="#">X</a></div>');
}
}, 'json');
$('#randomInsert').submit(function () {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function (o) {
$('#listInserts').append('<div>' + o.text + '<a class="del" rel="' + o.id + '" href="#">X</a></div>');
}, 'json');
return false;
});
});
EDIT Revised to only hit the DOM once on the insert, bind to the wrapper for the 'on() event handler:
$(document).ready(function () {
$('#listInserts').on("click", ".del", function () {
var delItem = $(this);
var id = delItem.attr('rel');
$.post('dashboard/xhrDeleteListing', {
'id': id
}, function (o) {
delItem.parent().remove();
}, 'json');
});
$.get('dashboard/xhrGetListings', function (o) {
var newlinks = ''
for (var i = 0; i < o.length; i++) {
newlinks = newlinks + '<div>' + o[i].text + '<a class="del" rel="' + o[i].id + '" href="#">X</a></div>';
}
$('#listInserts').append(newlinks);
}, 'json');
$('#randomInsert').submit(function () {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function (o) {
$('#listInserts').append('<div>' + o.text + '<a class="del" rel="' + o.id + '" href="#">X</a></div>');
}, 'json');
return false;
});
});

this is my solution for this jquery script with the latest lib:
$(function() {
$('#listInserts').on('click', '.del', function() {
var delItem = $(this);
var id = $(this).attr('rel');
$.post('dashboard/xhrDeleteListing', {'id': id}, function() {
delItem.parent().remove();
});
});
$.get('dashboard/xhrGetListings', function(o) {
for (var i = 0; i < o.length; i++) {
$('#listInserts').append('<div>' + o[i].text + ' <a class="del" rel="' + o[i].id + '" href="#">elimina</a></div>');
}
}, 'json'); // JSON = JavaScript Object Notation
$('#randomInsert').submit(function() {
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function(o) {
$('#listInserts').append('<div>' + o.text + ' <a class="del" rel="' + o.id + '" href="#">elimina</a></div>');
}, 'json');
return false;
});});
Hope this help.

Related

button function is not defined with htmlstring

I am able to display out all the details including the button. However, the main problem is that the when I click the button, nothing happens. It says that BtnRemoveAdmin() is not defined when I inspect for errors. However, I have function BtnRemoveAdmin()?? I have tried to move the function to htmlstring. Nothing works. I am not sure what went wrong.
(function () {
$(document).ready(function () {
showadmin();
});
function showadmin() {
var url = serverURL() + "/showadmin.php";
var userid = "userid";
var employeename = "employeename";
var role ="role";
var JSONObject = {
"userid": userid,
"employeename": employeename,
"role": role,
};
$.ajax({
url: url,
type: 'GET',
data: JSONObject,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (arr) {
_getAdminResult(arr);
},
error: function () {
alert("fail");
}
});
}
function _getAdminResult(arr) {
for (var i = 0; i < arr.length; i++) {
htmlstring = '<div class="grid-container">' +
'<div>' + arr[i].userid + '</div>' +
'<div>' + arr[i].employeename + '</div>' +
'<div>' + arr[i].role + '</div>' +
'<div>' + '<button onclick="BtnRemoveAdmin()">Remove</button>' + // 'BtnRemoveAdmin' is not defined
'</div>' ;
$("#name").append(htmlstring);
}
function BtnRemoveAdmin() {
var data = event.data;
removeadmin(data.id);
}
}
function removeadmin(userid) {
window.location = "removeadmin.php?userid=" + userid;
}
})();
All your code is defined inside an IIFE.
That includes BtnRemoveAdmin.
When you generate your JavaScript as a string, it is evaled in a different scope.
BtnRemoveAdmin does not exist in that scope.
Don't generate your HTML by mashing strings together.
Use DOM instead.
function _getAdminResult(arr) {
var gridcontainers = [];
for (var i = 0; i < arr.length; i++) {
var gridcontainer = $("<div />").addClass("grid-container");
gridcontainer.append($("<div />").text(arr[i].userid));
gridcontainer.append($("<div />").text(arr[i].employeename));
gridcontainer.append($("<div />").text(arr[i].role));
gridcontainer.append($("<div />").append(
$("<button />")
.on("click", BtnRemoveAdmin)
.text("Remove")
));
gridcontainers.push(gridcontainer);
}
$("#name").append(gridcontainers);
}
I use JQuery, and sometimes I get the same problem with plain JS functions not being called.
So I create JQuery functions :
$.fn.extend({
btnRemoveAdmin: function() {
...//Do what you want here
}
});
To call it use :
<button onclick="$().btnRemoveAdmin();"></button>
Hope it helps you !

Click event not working in javascript

I Follow This Article for Impalement CRUD Operation with HTML5 and Javascript.
So that Submit Data to Local Storage and save it.
my problem is Delete and Edit Operation when clicking on delete and edit button Nothing happens.
Javascript
$(function () {
var operation = "A";
var selected_index = -1;
var tbClients = localStorage.getItem("tbClients"); //Retrieve the stored data
tbClients = JSON.parse(tbClients); //Converts string to object
if (tbClients === null) //If there is no data, initialize an empty array
tbClients = [];
function Add() {
debugger;
var Data = {
ExternalProjects: {
Name: $('#Name').val(),
Body: $('#Body').val(),
Url: $('#Url').val()
}
};
tbClients.push(Data);
localStorage.setItem("tbClients", JSON.stringify(tbClients));
alert("The data was saved.");
List();
return true;
}
function Edit() {
tbClients[selected_index] = JSON.stringify({
Name: $('#Name').val(),
Body: $('#Body').val(),
Url: $('#Url').val()
}); //Alter the selected item on the table
localStorage.setItem("tbClients", JSON.stringify(tbClients));
operation = "A"; //Return to default value
return true;
}
function List() {
debugger;
var div = $('div#ExProjectList');
div.html("");
var cli = tbClients;
for (var i = 0; i < cli.length; i++) {
debugger;
div.append(
'<div href="#" class="list-group-item list-group-item-action flex-column align-items-start">' +
'<div class="d-flex w-100 justify-content-between">' +
' <h5 class="mb-1">' + cli[i].ExternalProjects.Name + '</h5>' +
' <small>' +
'<a id="btnDelete" alt="Delete' + i + '"><i class="fa fa-trash" style="cursor: pointer" ></i></a>' +
'<a id="btnEdit" alt="Edite' + i + '"><i class="fa fa-pencil" style="cursor: pointer"></i></a>'
+ '</small>' +
' </div>' +
'<p class="mb-1">' + cli[i].ExternalProjects.Body + '</p>' +
'<small>' + cli[i].ExternalProjects.Url + '</small>' +
'</div>'
);
}
}
function Delete() {
tbClients.splice(selected_index, 1);
localStorage.setItem("tbClients", JSON.stringify(tbClients));
}
$('#btnDelete').bind('click', function() {
selected_index = parseInt($(this).attr("alt").replace("Delete", ""));
Delete();
List();
});
$("#btnEdit").bind("click", function() {
operation = "E";
selected_index = parseInt($(this).attr("alt").replace("Edit", ""));
var cli = JSON.parse(tbClients[selected_index]);
$("#Name").val(cli.ExternalProjects.Name);
$("#Body").val(cli.ExternalProjects.Body);
$("#Url").val(cli.ExternalProjects.Url);
});
$("#AddExternalProject").click(function () {
if (operation === "A"){
return Add();
}
else{
return Edit();
}
});
});
You are creating the HTML dynamically, but not attaching the event to the element.
Instead of using:
$('#btnDelete').bind('click', function() {
selected_index = parseInt($(this).attr("alt").replace("Delete", ""));
Delete();
List();
});
$("#btnEdit").bind("click", function() {
operation = "E";
selected_index = parseInt($(this).attr("alt").replace("Edit", ""));
var cli = JSON.parse(tbClients[selected_index]);
$("#Name").val(cli.ExternalProjects.Name);
$("#Body").val(cli.ExternalProjects.Body);
$("#Url").val(cli.ExternalProjects.Url);
});
Use event delegation:
$("#ExProjectList").on("click", "#btnDelete", function() {
selected_index = parseInt($(this).attr("alt").replace("Delete", ""));
Delete();
List();
});
$("#ExProjectList").on("click", "#btnEdit", function() {
operation = "E";
selected_index = parseInt($(this).attr("alt").replace("Edit", ""));
var cli = JSON.parse(tbClients[selected_index]);
$("#Name").val(cli.ExternalProjects.Name);
$("#Body").val(cli.ExternalProjects.Body);
$("#Url").val(cli.ExternalProjects.Url);
});
If you are binding any event to any html element, always bind inside
$(document).ready(function(){
//code here
});
Because if you add the script earlier before Dom Content is ready, in self calling function then those elements will not be available to bind the events.

delete from database with javascript

I added a delete function to a todo list app that i built. The delete function works; however, when I refresh the page all the items that i deleted come back. How can I remove the items permanently from the database?
$(function() {
// The taskHtml method takes in a JavaScript representation
// of the task and produces an HTML representation using
// <li> tags
function taskHtml(task) {
var checkedStatus = task.done ? "checked" : "";
var liClass = task.done ? "completed" : "";
var liElement = '<li id="listItem-' + task.id +'" class="' + liClass + '">' +
'<div class="view"><input class="toggle" type="checkbox"' +
" data-id='" + task.id + "'" +
checkedStatus +
'><label>' +
task.title +
// '<button class="deletebutton" type="button">Delete</button>' +
'</label></div></li>';
return liElement;
}
// toggleTask takes in an HTML representation of the
// an event that fires from an HTML representation of
// the toggle checkbox and performs an API request to toggle
// the value of the `done` field
function toggleTask(e) {
var itemId = $(e.target).data("id");
var doneValue = Boolean($(e.target).is(':checked'));
$.post("/tasks/" + itemId, {
_method: "PUT",
task: {
done: doneValue
}
}).success(function(data) {
var liHtml = taskHtml(data);
var $li = $("#listItem-" + data.id);
$li.replaceWith(liHtml);
$('.toggle').change(toggleTask);
} );
}
$.get("/tasks").success( function( data ) {
var htmlString = "";
$.each(data, function(index, task) {
htmlString += taskHtml(task);
});
var ulTodos = $('.todo-list');
ulTodos.html(htmlString);
$('.toggle').change(toggleTask);
});
$('#new-form').submit(function(event) {
event.preventDefault();
var textbox = $('.new-todo');
var payload = {
task: {
title: textbox.val()
}
};
$.post("/tasks", payload).success(function(data) {
var htmlString = taskHtml(data);
var ulTodos = $('.todo-list');
ulTodos.append(htmlString);
$('.toggle').click(toggleTask);
$('.new-todo').val('');
});
});
//////this section works
$("#deletebutton").on("click", function() {
$(".todo-list li.completed").remove()
///////this does not want to remove the item from the database
$.destroy("/tasks/" + itemId, {
_method: "destroy",
task: {
done: doneValue
}
});
});
$(function() {
// The taskHtml method takes in a JavaScript representation
// of the task and produces an HTML representation using
// <li> tags
function taskHtml(task) {
var checkedStatus = task.done ? "checked" : "";
var liClass = task.done ? "completed" : "";
var liElement = '<li id="listItem-' + task.id +'" class="' + liClass + '">' +
'<div class="view"><input class="toggle" type="checkbox"' +
" data-id='" + task.id + "'" +
checkedStatus +
'><label>' +
task.title +
// '<button class="deletebutton" type="button">Delete</button>' +
'</label></div></li>';
return liElement;
}
// toggleTask takes in an HTML representation of the
// an event that fires from an HTML representation of
// the toggle checkbox and performs an API request to toggle
// the value of the `done` field
function toggleTask(e) {
var itemId = $(e.target).data("id");
var doneValue = Boolean($(e.target).is(':checked'));
// still dont understand this
$.post("/tasks/" + itemId, {
_method: "PUT",
task: {
done: doneValue
}
}).success(function(data) {
var liHtml = taskHtml(data);
var $li = $("#listItem-" + data.id);
$li.replaceWith(liHtml);
$('.toggle').change(toggleTask);
} );
}
$.get("/tasks").success( function( data ) {
var htmlString = "";
$.each(data, function(index, task) {
htmlString += taskHtml(task);
});
var ulTodos = $('.todo-list');
ulTodos.html(htmlString);
$('.toggle').change(toggleTask);
});
$('#new-form').submit(function(event) {
event.preventDefault();
var textbox = $('.new-todo');
var payload = {
task: {
title: textbox.val()
}
};
$.post("/tasks", payload).success(function(data) {
var htmlString = taskHtml(data);
var ulTodos = $('.todo-list');
ulTodos.append(htmlString);
$('.toggle').click(toggleTask);
$('.new-todo').val('');
});
});
$("#deletebutton").on("click", function() {
$(".todo-list li.completed").remove()
var li_to_delete = $('.todo-list li.completed');
$.ajax({
type: 'DELETE',
url: "/tasks" + li_to_delete,
success: function(){
li_to_delete.remove();
}
});
});
});
i changed the code but im not sure how to properly extract the url.

Defining a json parsing function outside `.ajax`

Fiddle Example
I'm working on a chained selectbox that populates options via Ajax and uses localStorage to save the returned data. The code is working but I want to simplify the code a little bit.
I want to know if it's possible to define the two $.each functions as a function outside the ajax code and call it back in the success function, like this example,but the tricky part is that the returned data is defined as data in the ajax success function while it's defined as key from the localStorage.
Failed Code:
function loop(){
$.each(data.query.results.json.json, function (index, i) {
smallchoice = i.choice.split('|');
$.each(smallchoice,function(j,smallchoice){
$option = $("<option/>").attr("value", smallchoice).text(i.bigcat + "#" +( i.cat || "") +"#" + smallchoice);
$select.append($option);
});
});
$select.dynamicDropdown({"delimiter":"#"});
}
$('select').each(function(loop){
$(this).one("mouseenter",function(){
var name = $(this).data('name'),
key = JSON.parse(localStorage.getItem(name)),
$select = $('select');var $option="";
$(this).addClass('yellow');
if (!key) {
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%20%3D%22http%3A%2F%2Fcheapgamessales.com%2F133.json%22&format=json&diagnostics=true&callback=",
success: function(data){
localStorage.setItem(name, JSON.stringify(data));
loop(data);
}
});
}
else{
loop(key);
}
});
});
Original Working Code:
$('select').each(function(){
$(this).one("mouseenter",function(){
var name = $(this).data('name');
var key = JSON.parse(localStorage.getItem(name));
var $select = $('select');var $option="";
$(this).addClass('yellow')
if (!key) {
$.ajax({
url: url,
success: function(data){
localStorage.setItem(name, JSON.stringify(data));
$.each(data.query.results.json.json, function (index, i) {
smallchoice = i.choice.split('|');
$.each(smallchoice,function(j,smallchoice){
$option = $("<option/>").attr("value", smallchoice).text(i.bigcat + "#" +( i.cat || "") +"#" + smallchoice);
$select.append($option);
});
});
$select.dynamicDropdown({"delimiter":"#"});
}
});
}
else{
$.each(key.query.results.json.json, function (index, i) {
smallchoice = i.choice.split('|');
$.each(smallchoice,function(j,smallchoice){
$option = $("<option/>").attr("value", smallchoice).text(i.bigcat + "#" +( i.cat || "") +"#" + smallchoice);
$select.append($option);
});
});
$select.dynamicDropdown({"delimiter":"#"});
}
}); // end one function
});
Like this?
function loop(data, $select){
$.each(data.query.results.json.json, function (index, i) {
smallchoice = i.choice.split('|');
$.each(smallchoice,function(j,smallchoice){
$option = $("<option/>").attr("value", smallchoice).text(i.bigcat + "#" +( i.cat || "") +"#" + smallchoice);
$select.append($option);
});
});
}
$('select').each(function(){
$(this).one("mouseenter",function(){
var name = $(this).data('name');
var key = JSON.parse(localStorage.getItem(name));
var $select = $('select');var $option="";
if (!key) {
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%20%3D%22http%3A%2F%2Fcheapgamessales.com%2F133.json%22&format=json&diagnostics=true&callback=",
success: function(data){
localStorage.setItem(name, JSON.stringify(data));
loop(data, $select);
$select.dynamicDropdown({"delimiter":"#"});
}
});
}
else{
loop(key, $select);
$select.dynamicDropdown({"delimiter":"#"});
}
});
});

Placing a div only after clicked object

Buildgames returns rows:
<a>....</a>
<a>....</a>
When I click on each a the Buildcar_s function returns all the data inside an alert.
Instead of this alert I want to put all the results in a div under each a, so it would look like:
<a>.....clicked ...</a>
<div>....
...
</div>
<a>....not clicked...</a>
<a>....not clicked...</a>
<a>....not clicked...</a>
How can we put a div only under the a which was clicked?
function Buildcar_s(items) {
var div = $('<div/>');
$.each(items, function() {
var car_ = this.car_;
$('<a>' + this.car_ + '----' + this.Names + '---' + '</a>').click(function() {
_Services.invoke({
method: 'GetgamesRows',
data: {
car_Number: car_
},
success: function(car_s) {
var div = Buildgames(car_s);
$(div).insertAfter($a);
}
});
}).appendTo(div);
$('<br/>').appendTo(div);
});
$("#leftRows").append(div);
}
function Buildgames(items) {
var place = '<div>';
$.each(items, function() {
place += 'mmmmmm<br/>';
});
place += '</div>';
return place;
}
Try this, relevant changes have been commented:
function Buildcar_s(items) {
var div = $('<div/>');
$.each(items, function() {
var car_ = this.car_;
$('<a>' + this.car_ + '----' + this.Names + '---' + '</a>').click(function() {
var $a = this;
_Services.invoke({
method: 'GetgamesRows',
data: {
car_Number: car_
},
success: function(car_s) {
var div = Buildgames(car_s);
// this inserts the HTML generated from the function,
// under the A element which was clicked on.
$(div).insertAfter($a);
}
});
}).appendTo(div);
$('<br/>').appendTo(div);
});
$("#leftRows").append(div);
}
function Buildgames(items) {
var place = '<div>';
$.each(items, function() {
place += '<div style="float: right;"> ' + this.CITY + ' ' + '</div><BR />' + +'<br/><br/>';
});
place += '</div>';
return place; // returns the string created, as opposed to alerting it.
}

Categories

Resources