Click event handler is called n-1 times the click number - javascript

On the page there is a list of dates. To the right of each date are two icons: update and delete. I want to catch the data-update_url, and data-delete_url.
The problem is that when I click on, say, update icon, nothing happens.
Another click makes it show alert message. Another click makes shows alert message twice. And so on. That is alert message is shown n-1 clicks number.
I tried to model it at jsfiddle. But failed.
Well, could you suggest what may be the reason of such behaviour?
<li>03 January 2016
<a class="update" id="update_framedate_26" href="javascript:void(0)"><span data-update_url="/frame_date/26/update/" class="glyphicon glyphicon-edit" aria-hidden="true"></span></a>
<a class="delete" id="remove_framedate_26" href="javascript:void(0)"><span data-delete_url="/frame_date/26/delete/" class="glyphicon glyphicon-remove" aria-hidden="true"></span></a>
</li>
<li>15 January 2015
<a class="update" id="update_framedate_27" href="javascript:void(0)"><span data-update_url="/frame_date/27/update/" class="glyphicon glyphicon-edit" aria-hidden="true"></span></a>
<a class="delete" id="remove_framedate_27" href="javascript:void(0)"><span data-delete_url="/frame_date/27/delete/" class="glyphicon glyphicon-remove" aria-hidden="true"></span></a>
</li>
<script>
function get_form(url){
var update_url = url.target.getAttribute('data-update_url');
var delete_url = url.target.getAttribute('data-delete_url');
var cuaghtUrl = update_url || delete_url;
alert(cuaghtUrl);
}
function handle_update_buttons(){
var update_button_list = $(".update");
$(update_button_list).click(function() {
$(this).click(get_form);
})
}
function handle_update_buttons(){
var update_button_list = $(".update");
$(update_button_list).click(function() {
$(this).click(get_form);
})
}
function handle_delete_buttons(){
var delete_button_list = $(".delete");
$(delete_button_list).click(function() {
$(this).click(get_form);
});
}
handle_update_buttons();
handle_delete_buttons();
</script>

This code hooks up a click handler that, every time it's called, will hook up a click handler calling get_form:
function handle_update_buttons(){
var update_button_list = $(".update");
// ------------------vvvvvv
$(update_button_list).click(function() {
$(this).click(get_form);
// --------^^^^^^
})
}
Note the arrows in the comments. So the first time, it just hooks up the second handler and that's all. The second time, it hooks up a handler again and then the handler from the first call is fired. The thrid time, it hooks up a handler for the third time, and the first two handlers are triggered. And so on.
You probably meant to do this:
function handle_update_buttons(){
$(".update").click(get_form);
}
...which just hooks up a handler once, which will call get_form on each click.

That's because you are adding another handler on every click event.
Let's look at your code:
$(update_button_list).click(function() {
$(this).click(get_form);
})
What it does is:
It attaches a "click" event handler, which, when invoked (when a user click on your element):
Will attach get_form callback on $(this) element
I assume you wanted to simply invoke your get_form callback on first click, so instead of reattaching it (again and again on every other click), just call it:
$(update_button_list).click(function() {
var url = ... set this variable to whatever you want it to be ...
get_form(url);
})

Problem with your code is you are attaching click event all the time.
It dosnt required to be attached all the time.
Please look at below code here
$(update_button_list).click(function() {
get_form($(this));
})
attached only one time it works all the time.
Hope this helps.
function get_form(url) {
var update_url = url.parent().find('span[data-update_url]').attr('data-update_url');
var delete_url = url.parent().find('span[data-update_url]').attr('data-delete_url');
var cuaghtUrl = update_url || delete_url;
alert(cuaghtUrl);
}
function handle_update_buttons() {
var update_button_list = $(".update");
$(update_button_list).click(function() {
get_form($(this));
})
}
function handle_update_buttons() {
var update_button_list = $(".update");
$(update_button_list).click(function() {
get_form($(this));
})
}
function handle_delete_buttons() {
var delete_button_list = $(".delete");
$(delete_button_list).click(function() {
get_form($(this));
});
}
handle_update_buttons();
handle_delete_buttons();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<li>03 January 2016
<a class="update" id="update_framedate_26" href="javascript:void(0)"><span data-update_url="/frame_date/26/update/" class="glyphicon glyphicon-edit" aria-hidden="true"></span></a>
<a class="delete" id="remove_framedate_26" href="javascript:void(0)"><span data-delete_url="/frame_date/26/delete/" class="glyphicon glyphicon-remove" aria-hidden="true"></span></a>
</li>
<li>15 January 2015
<a class="update" id="update_framedate_27" href="javascript:void(0)"><span data-update_url="/frame_date/27/update/" class="glyphicon glyphicon-edit" aria-hidden="true"></span></a>
<a class="delete" id="remove_framedate_27" href="javascript:void(0)"><span data-delete_url="/frame_date/27/delete/" class="glyphicon glyphicon-remove" aria-hidden="true"></span></a>
</li>

Related

How to append big HTML snippets into DOM with Javascript?

I have an app which uses EJS templating to populate data.
In order to add new projects I have made a simple input form which takes all required parameters.
After an input completed an Ajax request being sent, on success I want to inject this snippet into DOM.
In simple words - After new project added I want to display play instantly by injecting into DOM without reloading the page
Is there an elegant way of inserting this div ladder as a template into DOM? It works,
<div class="projects">
<div class="projectHeader">
<div class="projectTitle">
<span>
<a data-toggle="modal" data-target="#editDeadLineModal">
<i data-id="<%=project.id%>" class="projectDeadline far fa-calendar-alt fa-2x" data-toggle="tooltip" data-placement="top" title="Set Deadline"></i>
</a>
</span>
<h5 class="projectName <%=project.id%>" data-toggle="tooltip" data-placement="top" title="Deadline <%=deadline%>" style="align-items: center;">
<%=project.name%>
</h5>
<%}%>
<div class="projectButtons">
<span data-toggle="tooltip" data-placement="top" title="Edit Project Title">
<a data-toggle="modal" data-target="#editProjectTitleModal">
<i id="editProjectName" class="editProject fas fa-pencil-alt" data-name="<%=project.name%>" data-id="<%=project.id%>"></i>
</a>
</span>
<i class="separatorDash fas fa-minus"></i>
<span data-toggle="tooltip" data-placement="top" title="Delete Project">
<a data-toggle="modal" data-target="#deleteProjectModal">
<i id="deleteProject>" class="deleteProject far fa-trash-alt" data-id="<%=project.id%>"></i>
</a>
</span>
</div>
</div>
</div>
</div>
What I have tried is recreating the entire div ladder in string and append it to parent node.
Like this:
// Add new Project
$('#addNewProjectBtn').on("click", function() {
$("#newProjectModal").on('show.bs.modal', function() {
$(".confirmNewList").on("click", function(event) {
var url = '/addNewList';
var newListTitle = $("#newListNameInput").val()
event.preventDefault();
$.post({
url: url,
data: {
listName: newListTitle
},
success: function(result) {
$("#newProjectModal").modal('hide')
$("#newListNameInput").val('');
var id = result.data.id
var name = result.data.name
//Append new project
$(".projects").append("<div class='project col-4' id='project" + id + "'> <div class='projectHeader'> <div class='projectTitle'> ...and so on until the end")
},
error: function(err) {
console.log(err);
}
})
}
}
})
})
})
In simple words - After new project added I want to display play instantly by injecting into DOM without reloading the page
Is there an more elegant and specially efficient way of inserting this div ladder as a template into DOM?
The method which I have tried above - works, But on attempt to interact with it by calling modals - modals do not get it's data-*, as well the bootstrap tooltips don't work.
you can try create new html file instead, and append like this in your page
$.get("yourfile.html", function (data) {
$("#appendToThis").append(data); // or use .html();
});
OR you can directly pass this HTML structure from your backend, so you can directly use append function.
After some research I discovered that the event handler can be delegated.
Since the html snippet I am trying to append to projects is added after document.ready (document is loaded and handlers are bind) the only thing required to make the new snippet be active on event is to delegate the event handler to the parent of element that is appended.
Like this :
$("body").delegate("#addNewProjectBtn", "click", function() {
$("#newProjectModal").on('show.bs.modal', function() {
$(".confirmNewList").on("click", function(event) {
var url = '/addNewList';
var newListTitle = $("#newListNameInput").val()
event.preventDefault();
$.post({
url: url,
data: {
listName: newListTitle
},
success: function(result) {
$("#newProjectModal").modal('hide')
$("#newListNameInput").val('');
var id = result.data.id
var name = result.data.name
//Append new project
$(".projects").append("<div class='project col-4' id='project" + id + "'> <div class='projectHeader'> <div class='projectTitle'> ...and so on until the end")
},
error: function(err) {
console.log(err);
}
})
}
}
})
})
})
By delegating the event handler to it's parent - the event handler is preserved in the parent.

How to remove an entry from localstorage in javascript?

I store some data in a localstorage in my Javascript file. I want to create a delete button on the details grid that allows me to delete an individual item. I need to first identify the key of the selected item and then use the localStorage.removeItem(key) method to delete the item. But my method doesn't seem to work.
This is in my factory:
removeItem: function (data) {
var prefixLength = prefix.length;
Object.keys(localStorage)
.forEach(function (key) {
if (key.substring(0, prefixLength) == data) {
var item = window.localStorage[key];
localStorage.removeItem(key);
}
});
},
Then I call it in my controller.js:
$scope.remove = function () {
expService.removeItem($scope.expense);
},
my button is:
<button type="button"class="btn btn-sm btn-danger pull-right" id="remove" ng-click="remove()">
<span class="glyphicons glyphicons-bin"></span>
</button></div>
In my case, I had to delete a localstorage data on button click. Here is how I achieved that.
<button onclick="deleteFavorite('Id or name what you set as key')"> Delete </button>
function deleteFavorite(Id){
localStorage.removeItem(Id);
}
Please note that you can add id dynamically to the function using javascript and you have to reload the page to see if the item is deleted or not.
I didnt see error but simple to do it
<button type="button"class="btn btn-sm btn-danger pull-right" id="remove" ng-click="remove(expense)">
<span class="glyphicons glyphicons-bin"></span>
</button>
and js
$scope.remove = function (itemTodelete) {
localStorage.removeItem(itemTodelete);
},
localStorage.removeItem('itemTodelete');
localStorage.remove('itemTodelete'); or
localStorage.clear();

data-bind in the .js file

I am writing in .js file and trying to loop through each element and add this "self.renderButtons". when i click on delete it should call the remove function. It is not doing that, can anyone help?
self.renderButtons = function (id) {
return ('<span class="fa fa-file-text-o"></span> Details'
+ '<button class="btn btn-sm btn-danger" data-bind="click: removeItem"><span class="glyphicon glyphicon-trash"></span> Delete</button>');
}
self.removeItem = function (item) {
$(document).trigger('loader-show');
self.service.delete(item.Id, self.handleDelete, self.handleError);
};
Manipulating the DOM is Knockout's job. If you want to have a button that corresponds to each element of an array, that is a job for the foreach binding. You manipulate the observableArray, and Knockout will take care of making the DOM reflect that state.

Add Friend with Ajax - Django

I'm using Django-Friends
I'm trying to have it so when a user clicks on the add friend, the button disappears(or ideally says Request sent). However, when I click the button, it doesn't disappears. I am new at Django and Ajax, so I'm assuming that this is an error on my part. Most likely the HttpResponse.
That part actually confuses me a lot. The HttpResponse, render, render_to_response, etc. I know that I can use render or render_to_response when I want to load a template. But what if I don't want to load up a new template or go to a new page? Like I want to be able to complete an action like add a friend, or add a page, etc; all on one page. I know you can use ajax to do it, but I don't know the django technical aspect of it.
Anyway, here's my code. Right now, nothing happens. The button doesn't disappear, and there is no friendships request sent.
profile.html
<div class="text-center">
<div>
"{{currUserprofile.tagline}}"
</div>
{{currUser.profile.city}}, {{currUser.profile.state}}
{{currUser.id}}
</div>
<!-- <button id="addfriend" data-profileid="{{currUser.id}}" class="btn btn-primary" type="button"> <span class="glyphicon glyphicon-plus"></span>
Request Friend</button>
--> <!--Find a way to signify looking or not looking to mentor -->
<button id="addfriend" data-profileid="{{currUser.id}}" class="btn btn-primary" type="button"> <span class="glyphicon glyphicon-plus"></span>
Request Friend</button>
ajax.js
$(document).ready(function () {
$('#addfriend').click(function () {
var profile_id = $(this).data("profileid");
$.get('/myapp/addfriend/id=' + profile_id, function (data) {
$('#addfriend').fadeOut();
});
});
})
views.py
#login_required
def profile(request, id):
context = RequestContext(request)
currUser = User.objects.get(pk = id)
profile = UserProfile.objects.filter(user = currUser)
return render_to_response('myapp/profile.html', {'currUser': currUser, 'UserProfile': UserProfile}, context)
#login_required
def addfriend(request, id):
context = RequestContext(request)
other_user = User.objects.get(pk=id)
new_relationship = Friend.objects.add_friend(request.user, other_user)
profile = UserProfile.objects.filter(user = other_user)
return HttpResponse(new_relationship)
Here is a working JSFiddle, but you can't post data {profile_id: profile_id}with a getyou should use a postor add the data as params, as I did:
HTML:
<button id="addfriend" data-profileid="{{currUser.id}}" class="btn btn-primary" type="button"> <span class="glyphicon glyphicon-plus"></span>
Request Friend</button>
JS:
$(document).ready(function () {
$('#addfriend').click(function () {
var profile_id = $(this).data("profileid");
$.get('/myapp/addfriend/?profile_id=' + profile_id, function (data) {
$('#addfriend').fadeOut();
});
});
});

twitter bootstrap modal -- how to pass data to callback function

is there a way to pass additional data to bootstrap modal function callback?
for example, lets say my link that causes the modal to open has an extra attribute in it with a bit of useful data in it, how could I reference that attr?
HTML
<span listid="80" href="#editTaskList" data-toggle="modal" class="btn btn-mini right"><i class="icon-edit"></i> Edit Task List</span>
JS
$('#editTaskList').on('show', function () {
// get the source of the click, and then get the data i need.
});
Could this work for you ?
<span listid="80" href="#editTaskList" data-toggle="datamodal" class="btn btn-mini right"><i class="icon-edit"></i> Edit Task List</span>
var $editTaskList = $('#editTaskList');
$('body').on('click.modal.data-api', '[data-toggle="datamodal"]', function (e) {
var $this = $(this);
$editTaskList.data('anyAttr',$this.data('anyAttr'));
$editTaskList.modal('show');
e.preventDefault();
})
$editTaskList.on('show', function () {
var myData = $editTaskList.data('anyAttr');
});
I know that this is an old question, but this is the first thing i've found on google. So, I want to put some important information here...
You NEED to put your callback function binded on events BEFORE you call the modal, for example:
$('#modal').on('shown', function(){
// Do something when the modal is loaded
});
$("#modal").modal();
This is very important and helped me a lot, so, here it is...
Like this -
<span id="modal_opener" data-extrastuff="stuff" listid="80" href="#editTaskList" data-toggle="modal" class="btn btn-mini right"><i class="icon-edit"></i> Edit Task List</span>
$('#modal_opener').click(function() {
var stuff_i_want = $(this).attr('data-extrastuff');
});

Categories

Resources