jQuery Eventhandler for an dynamically added object - javascript

I got an problem with dynamically added DOM objects in jQuery. First of all I use this:
var $input = $('#search-input');
var $usersList = $('#ulist');
$input.on('input', function () {
$.ajax({
type: 'get',
url: '/userlist',
data: {query: $input.val()},
success: function (response) {
var json = JSON.parse(response);
$usersList.empty();
$.each(json, function (index, val) {
$usersList.append("<div id=\"listelem\">" + val + "</div>");
});
}
});
});
<div id="ulist"></div>
<input id="search-input" type="text">
to insert divs into usersList. This works well, but now I want to get val from this div when I click on it to process it further. I wrote this piece of code:
$usersList.on('click','#listelem', function(){
alert("clicked");
});
When I click on div I got proper alert, but now I have no idea how could I took data from inside of this element.

I don't know the proper engineering but I have dealt with similar issue while I was developing some requirements. basically as I understood you want to find out the target of the event and drag a value from there? if so you can do something like this:
jQuery(document).on('click', '#listelem', function(event){
var x = event.target.val();// event.target.value; depending on your situation and availability of the method.
});
Hope this helps.

try this
$(document).on('click','#listelem', function(event) {
alert($(event.target).text());
});
jsfiddle

Thanks you for help. for me proper option was to call
var mem =event.target.innerText;

you can do that with the regular javascript, you don't need Jquery.
document.addEventListener("click", function(e) {
if(e.target) {
console.log("item clicked ", e.target.textContent);
}
});
This should do the job to get the value of current target.

Related

How do I assign a jQuery object to a variable?

So I have two autocomplete containers. Instead of writing code twice, I will use the same autocomplete call.
But in order to triger correct autocomplete (read: populate correct result list), I need to assign it to a variable. I've done this a long time ago, but I have forgotten how I did it.
So I have the following:
autocomplete: function () {
var autocompleteInput = null;
var autocompleteResultList = null;
$('.autocomplete').on("input", function (e) { // I have 2 of these
autocompleteInput = $(this); // This is the input i'm working with
autocompleteResultList = autocompleteInput.closest('.autocomplete-result');
resourcesData(autocompleteInput.val());
}).on('focus', function (e) {
autocompleteInput.val(''); //Cannot read property 'val' of null
}).on('blur', function (e) {
autocompleteResultList.removeClass('is-active');
});
}
My HTML x 2 (short version)
<div class="autocomplete-wrapper">
<input class="autocomplete" type="text" >
<input class="resource-id" type="hidden">
<div class="autocomplete-result"></div>
</div>
I'm pretty sure it' some basic jQuery knowledge in regards of setting a variable = a jQuery object (autocompleteInput = $(this);) and how it all works that I've forgotten.
Any help appreciated :)
PS. I'm not using jQuery autocomplete - I've made my own.
You have to abandon the variables that you share across the different event callbacks. But since they are easy to derive, just do that in each event handler itself.
Some things to note:
The closest method only looks to parents, not to siblings, so use the siblings method instead (or if your structure is slightly different than in your question, maybe .closest(".autocomplete-wrapper").find(".autocomplete-result")).
resourcesData is currently not provided with any information about where it should populate the data, so you should pass it an extra argument for it to know where to populate, and deal with that argument in that function.
Suggested code would then be:
autocomplete: function () {
$('.autocomplete').on("input", function (e) {
// extra argument
resourcesData($(this).val(), $(this).siblings('.autocomplete-result'));
}).on('focus', function (e) {
$(this).val('');
}).on('blur', function (e) {
$(this).siblings('.autocomplete-result').removeClass('is-active');
});
}
So after good help from Patric, Baao and Trincot (and others), I got it working. So just want to share my working solution just incase others are facing similar issues. It's probably not the most elegant solution, but it's working :)
let resources = {
init: function () {
this.searchResources();
},
searchResources: function () {
var self = this;
$('.autocomplete').on("input", function (e) {
let term = $(this).val();
if(term.length > 1){
self.autocomplete($(this));
}
}).on('focus', function (e) {
$(this).val('');
}).on('blur', function (e) {
$(this).closest('.autocomplete-result').removeClass('is-active');
});
},
autocomplete: function(obj){
let url = 'http://localhost.no:8080/resources%TERM';
url = url.replace('%TERM', '/' + $(obj).val() );
var resultList = $(obj).siblings('.autocomplete-result');
let source = $('#autocomplete-list').html();
let template = Handlebars.compile (source);
$.ajax({
method: "GET",
url: url,
dataType: "json",
success: function(result) {
let content = template({resources: result.data});
$(resultList).html(content);
$('.autocomplete-list-item').on('click', function (e) {
$(obj).siblings('input.resource-id').val($(this).data('resource-id'));
$(obj).val($(this).data('resource-name'));
$(resultList).removeClass('is-active');
console.log($(this).data('resource-id'));
console.log($(this).data('resource-name'));
});
},
error: function(err){console.log(err);}
}).done(function () {
var resultList = $(obj).siblings('.autocomplete-result');
if(!$(resultList).hasClass('is-active')){
$(resultList).addClass('is-active')
}
});
}
};
One of my input fields looks like this:
<div class="input-field column is-6 autocomplete-wrapper">
<input id="autocomplete-owner" class="autocomplete" autocomplete="off" type="text" >
<label for="autocomplete-owen">Prosjektleder</label>
<input id="resource-id-owner" class="resource-id" type="hidden" name="resource-id-owner">
<div class="autocomplete-result"></div>
</div>

Getting Data from button click for Jquery

I am using the "Second Solution" from this problem:
call the same jQuery function in multiple buttons
I am dynamically creating my buttons, based on an input, so there is currently 45 buttons! (used to select page number)
Is there a way to use the value of the button as data in my $.get so I can pull the data for the page?
$('.bclick').click(function(){
$.getJSON("url", { page: [need button data here] }, function(data){
//Some actionable code
})
});
.bclick is the class given to each of the buttons created.
when you are inside of the function, the reserved word this is a reference to your clicked button.
$('.bclick').click(function(){
var page = $(this).val();
$.getJSON("url", { page: page }, function(data){
//Some actionable code
})
});
If your buttons are created dinamically probably this solution won't work. I may suggest you to use $.on():
$("parent selector or form selector").on("click", ".bclick", function(){
var page = $(this).val();
$.getJSON("url", { page: page }, function(data){
//Some actionable code
})
})
If you are generating buttons dynamically, then use .on.
$(function(){
$(document).on("click", ".blick", function(){
var $this = $(this);
var buttonName = $this.attr("name");
});
});
Sample code
Yes you can by adding an extra attribute to your .bclick element, for example
<button class="bclick" data="your data here"></button>.
Then
$('.bclick').click(function(){
var buttonData = $(this).attr('data');
$.getJSON("url", { page: buttonData }, function(data){
//Some actionable code
})
});

jQuery function doesn't work after after loading dynamic content

I'm using below code. This is bootstrap 3 delete conformation message.
$(document).ready(function(){
$('a.btnDelete').on('click', function (e) {
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
$('#btnDelteYes').click(function () {
var id = $('#myModal').data('id');
var dataString = 'id='+ id ;
$('[data-id=' + id + ']').parent().remove();
$('#myModal').modal('hide');
//ajax
$.ajax({
type: "POST",
url: "delete.php",
data: dataString,
cache: false,
success: function(html)
{
//$(".fav-count").html(html);
$("#output").html(html);
}
});
//ajax ends
});
});
This is the trigger element that I'm using
<div data-id="MYID"><a class="btnDelete" href="#">Delete</a></div>
And I'm using the same HTML element dynamically to trigger delete and it doesn't work.
Can someone point me the correct way to do it?
You have to use event delegation
$(document).on("click" , '#btnDelteYes' ,function () {
Pretty much: bind the click higher up to something that exists when the script is run, and when that something is clicked, tell it to pass the click event to the #btnDelteYes element instead
I cant understand what exactly you are doing on your code due to missing information, but the answer is: you should use event delegation on the dynamically inserted content
you can try
$('[data-id=MYID]').on('click','.btnDelteYes',function({
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
here <div data-id="MYID"> should be a hard coded html content and The idea is to delegate the events to that wrapper, instead of binding handlers directly on the dynamic elements.

livequery doesn't bind after a DOM insertion

I don't understand why livequery doesn't bind the event, but I have to use .click.
This is just an example, which might also use the .click(), but in the real code I'm forced to use livequery.
Does anyone know why livequery isn't working?
function bind_remove(comment){
var id = comment.attr('comment_id');
comment.find(".remove").livequery("click", function(e){
$.post("/deleteComment", {id: id}, function(response){
comment.remove();
comments = comments_container.find('.comment');
});
});
}
$(document).ready(function(){
var comments_container = $('#comments_container');
var comments = comments_container.find('.comment');
comments.each(function(){
bind_remove($(this));
});
$(".submit_button").livequery("click", function(e){
$.post("/newComment", {text: textarea.val()}, function(response){
comments_container.last().append($(response).fadeIn('slow',function(){
comments = comments_container.find('.comment');
bind_remove(comments.last());
}));
});
});
});
Try replacing
comment.find(".remove").livequery("click", function(e){
with this
comment.find(".remove").live("click", function(e){
I added a random id to the last comment, then I selected it with $('#myid'), not using 'last()'. Then I bind it and started to work

Javascript Jquery doesn't work. $(this)

$(document).ready(function() {
$(".delete_user_button").click(function(){
var username_to_delete = $(this).attr('rel');
$.ajax({
type:"POST",
url:"/delete/",
data:{'username_to_delete':username_to_delete},
beforeSend:function() {
$(this).val("Removing...");
},
success:function(html){
$("div.delete_div[rel=" + username_to_delete + "]").remove();
}
});
return false;
});
});
Why doesn't $(this).val() work?
I'm trying to change the text of the button when the user clicks remove.
In your event handler (beforeSend), this refers to the XMLHttpRequest object used for the ajax call, not your original this of the click event handler. You should "capture" it in a variable first:
$(document).ready(function() {
$(".delete_user_button").click(function(){
var element = $(this);
var username_to_delete = element.attr('rel');
$.ajax({
type:"POST",
url:"/delete/",
data:{'username_to_delete':username_to_delete},
beforeSend:function() {
element.val("Removing...");
},
success:function(html){
$("div.delete_div[rel=" + username_to_delete + "]").remove();
}
});
return false;
});
});
This mechanism is called "closures". For an interesting explanation of this, check this link:
http://www.bennadel.com/blog/1482-A-Graphical-Explanation-Of-Javascript-Closures-In-A-jQuery-Context.htm
Without more knowledge about the context or analysing the script itself: Keep in mind that, in certain environments, it might be possible that $ itself does not work and needs to be replaced with jQuery - I've seen this in Liferay.
I guess this is not your problem here, but it might come in handy for others looking for this problem from another context.

Categories

Resources