jQuery mobile - how to connect between <a href> and the click event? - javascript

I'm a newbie to jQuery and jQuery mobile.
I followed a few samples and documentations and created the following code:
function initListByUrl(id, requestUrl) {
$.ajax({
url: requestUrl,
type:'GET',
dataType:'json',
success: function(data) {
var items = []
$.each(data, function(i, elem) {
items.push('<li id="cat_li_'+i+'">' + elem.name + '</li>');
});
id.html(items).listview('refresh');
}
});
}
$(document).on("click", '[id^=cat_li]', function(event, ui) {
console.log(3);
})
I need to have the elem event from the $.ajax available in the context of the click event
This is because the elem object holds a field that is relevent when the item is clicked.
How should I do it?
EDIT
just to clarify.
the initListByUrl functions is called in document-ready. It builds a list view by the retrieved json object which contains an array.
if I had elem in the context of the on-click event I would have done something like this:
$(document).on("click", '[id^=cat_li]', function(event, ui) {
call_some_function(elem.someField);
})
My issue is how do I have the appropriate elem object in the scope of the on-click event?
EDIT 2
This is my full code:
var stack = []
var site_url = 'http://localhost:3000';
$(function() {
initCategoriesList();
$("#places").on('pageinit', function() {
var category = stack.pop();
initPlacesList(category);
});
$("#place").on('pageinit', function() {
});
});
function initCategoriesList(id, requestUrl) {
$.ajax({
url: site_url + '/categories',
type:'GET',
dataType:'json',
success: function(data) {
var items = []
$.each(data, function(i, elem) {
items.push('<li id="cat_li_'+i+'">' + elem.name + '</li>');
});
$("#categories_ul").html(items).listview('refresh');
}
});
}
function initPlacesList(category_id) {
$.ajax({
url: site_url + '/business_places/category/' + category_id,
type:'GET',
dataType:'json',
success: function(data) {
var items = []
$.each(data, function(i, elem) {
items.push('<li id="place_li_'+i+'">' + elem.name + '</li>');
$("#places_ul").html(items).listview('refresh');
var element = $("#place_li_" + i)[0];
$.data(element, "object", elem);
});
$("#places_ul").html(items).listview('refresh');
}
});
}
$(document).on("click", '[id^=cat_li]', function(event, ui) {
stack.push(event.target.innerText);
})
$(document).on("click", '[id^=place_li]', function(event, ui) {
var place = $.data(this, "object");
alert(place.name);
})
var place = $.data(this, "object");
ends up having undefined

Your best bet is going to be to create custom data attributes inside the li element to be accessed at a later time. Push the data you need to these custom attributes. Example:
items.push('<li id="cat_li_'+i+'" data-custom-cool="' + elem.someData + '">' + elem.name + '</li>');
Now, you can pull out the data as you need it with this inside your click handler.
$(this).data("custom-cool"); //this is equiv to elem.someData .
Or, if you have bigger data, you can store the object with the element with $.data:
$.each(data, function(i, elem) {
items.push('<li id="cat_li_'+i+'">' + elem.name + '</li>');
});
id.html(items).listview('refresh');
var element = $("#cat_li_" + i)[0]; //cant use jQ object
$.data(element, "object", elem); //assign object
});
Now your click handler should be able to access the object like so (inside handler):
console.log($.data(this, "object").objProperty); //replace objProperty with your property to get.
Demo: http://jsfiddle.net/tymeJV/vx8Xt/1/ Click on "testdiv" and see the console.

I think the problem is with id.html(items), .html() doesn't accept an array.
id.html(items.join('')).listview('refresh');
Also to fix your other problem, you should use classes instead of ids :
function initListByUrl(id, requestUrl) {
$.getJSON(requestUrl, function(data) {
var items = []
$.each(data, function(i, elem) {
items.push('<li class="cat">' + elem.name + '</li>');
});
id.html(items).listview('refresh');
});
}
$(document).on("click", '.cat a', function(event, ui) {
console.log(3);
});

Like ajax is asynchronous by default, you have two options:
You can make the ajax request synchronous by switching the option async to false - for more details, see jQuery.ajax() API
You can save the elem in a global variable and use it in the onclick-handler
Maybe it would also be helpful if you tell us, when the function initListByURL() is executed.

You should move the event binding into the success function, after all item in the list has been attached to Document
success: function(data) {
var items = []
$.each(data, function(i, elem) {
items.push('<li id="cat_li_'+i+'">' + elem.name + '</li>');
});
id.html(items).listview('refresh');
// move your click event handling here
}

Related

e.preventDefault does still loads anchor link in a new tab in browser

I have basically a ajax call that invokes a REST API that gives me list of all names and I have another REST API that matches that. For example,
/list gives me: list1,list2,list3
and
/api/list1.json gives me: json of list1..
But I have my code where I loop through all the lists and invoke /api/list1.json
I want that JSON to be displayed in a div when a onclick event occurs by grabbing the href accordingly without page reload. But right now, since that is also a valid link browser just takes me there.
Here is my code:
$(function() {
$.ajax({
dataType: 'json'
url: '/lists',
success: function (data) {
if (data != null) {
var html = '<ul>';
$.each(data.apis, function (i, item) {
//click event
$('a').click(function(e) {
e.preventDefault();
});
html += '<li class="res">';
html += '<div class="hed"><h2>' + item + '</h2></div>';
html += '</li>';
});
html += '</ul>';
$('#exDiv').empty();
$('#exDiv').append(html);
}
},
error: function () {
alert('Error');
},
contentType: 'application/json'
});
$('a').click(function(e) {
e.preventDefault();
});
});
Apparently I also added e.preventDefault() but it still triggers the link to a new tab.
Link to e.preventDefault()
These are dynamically added anchor tags. They don't exist when you add the click event handler to the anchor tags. So when you click these anchors they are going to bypass your jquery event handlers and do what they normally do by default.(further explanation) You have the same code again inside the $.each function which might have worked if you had called it after your $('#exDiv').append(html); line. But again they still don't exist when you call it.
Depending on the version of jQuery you're using you should use either "on" or "live". If you are using a version 1.7 or higher use 'on'.
Try this:
$(function() {
$.ajax({
dataType: 'json'
url: '/lists',
success: function (data) {
if (data != null) {
var html = '<ul>';
$.each(data.apis, function (i, item) {
html += '<li class="res">';
html += '<div class="hed"><h2>' + item + '</h2></div>';
html += '</li>';
});
html += '</ul>';
$('#exDiv').empty();
$('#exDiv').append(html);
}
},
error: function () {
alert('Error');
},
contentType: 'application/json'
});
$(document).on('click', 'a', function(e) {
e.preventDefault();
});
});
If you're using 1.6 or ealier your click event handler should look like this:
$('a').live('click', function(e) {
e.preventDefault();
});

AJAX jQuery on click dynamically created only works first time

I am trying to create a dropdown menu that I dynamically insert into using jQuery. The objects I'm inserting are notifications, so I want to be able to mark them as read when I click them.
I have an AJAX call that refreshes the notifications every second from the Django backend.
Once it's been refreshed, I insert the notifications into the menu.
I keep an array of the notifications so that I don't create duplicate elements. I insert the elements by using .append(), then I use the .on() method to add a click event to the <li> element.
Once the click event is initiated, I call a function to .remove() the element and make an AJAX call to Django to mark the notification as read.
Now my problem:
The first AJAX call to mark a notification as read always works. But any call after that does not until I refresh the page. I keep a slug value to identify the different notifications.
Every call I make before the refresh uses the first slug value. I can't figure out why the slug value is tied to the first element I mark as read.
Also, if anyone has a better idea on how to approach this, please share.
Here's my code:
var seen = [];
function removeNotification(elem, urlDelete) {
elem.remove();
console.log("element removed");
$.ajax({
url: urlDelete,
type: 'get',
success: function(data) {
console.log("marked as read");
},
failure: function(data) {
console.log('failure to mark as read');
}
});
}
function insertNotifications(data) {
for (var i = 0; i < data.unread_list.length; i++) {
var slug = data.unread_list[i].slug
var urlDelete = data.unread_list[i].url_delete;
if (seen.indexOf(slug) === -1) {
var elem = $('#live-notify-list').append("<li id='notification" +
i + "' > " + data.unread_list[i].description + " </li>");
var parent = $('#notification' + i).wrap("<a href='#'></a>").parent();
seen.push(slug);
$( document ).ready(function() {
$( document ).on("click", "#notification" + i, function() {
console.log("onclick " + slug);
removeNotification(parent[0], urlDelete);
});
});
}
}
}
function refreshNotifications() {
$.ajax({
url: "{% url 'notifications:live_unread_notification_list' %}",
type: 'get',
success: function(data) {
console.log("success");
insertNotifications(data);
},
failure: function(data) {
console.log('failure');
}
});
}
setInterval(refreshNotifications, 1000);
I really don't know what do you mean with parent[0] in
removeNotification(parent[0], urlDelete);
I think you can simply try $(this)
removeNotification($(this), urlDelete);
but to be honest I find to put
$( document ).ready(function() {
$( document ).on("click", "#notification" + i, function() {
console.log("onclick " + slug);
removeNotification(parent[0], urlDelete);
});
});
inside a loop .. its bad thing try to put it outside a function and use it like
$( document ).ready(function() {
setInterval(refreshNotifications, 1000);
$( document ).on("click", "[id^='notification']", function() {
console.log("onclick " + slug);
removeNotification($(this), urlDelete);
});
});
and try to find a way to pass a urlDelete which I think it will be just one url

Jquery Ajax : auto-refresh

In my Ajax success function i created button and on click i am calling a function.
The problem:
The page reloads based on the timer in set interval but when i click the button it will call the function based on the number of times the page reloaded.
For example:
If page reloads 5 times and then i call a function on clicking that button-it will call that function 5 times.
if it reloads 10 times then function call is for 10 times.
Please advice what i am doing wrong?
Here is the code:
$(document).ready(
function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = ('<button id="bt21" class="btn121">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
$(document).on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
}
});
}, 5000);
});
You have set the AJAX call to be made every 5 seconds. Each time time this function is called, you are also attaching the click event on the button you append. So there will be multiple event handlers attached to the same element. You need to clear any existing event handlers on that element before you attach another if you want to stick to your current code. Here's how to do it:
$(document).off('click', '#bt21');
$(document).on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
Each time the page is refreshed from your ajax call a new event listener is bound to the button in memory. You need to clear the event listeners then create a new one.
$(some element).unbind().on(...........);
I always unbind event listeners created in an ajax call if anything to keep the browser memory from being over loaded or to prevent the issue you are having.
$(document).ready(
function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = ('<button id="bt21" class="btn121">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
$(document).unbind().on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
}
});
}, 5000);
});
First you are appending buttons on refresh that have the same id attribute so that's going to cause you issues at some point.
What you need to do is move your click event outside of the interval function and ajax callback. Add the process id to the button in a data attribute and delegate a click event to the button so it will work even though the elements haven't been created in the DOM when the page loads.
Here's an example although I'm not sure if it works (can't really simulate this easily):
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = '<button class="btn" data-process-id="' + item.process_id + '">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
}
});
}, 5000);
$('#test1').on('click', '.btn', function() {
stopTest( $(this).data('process_id') );
});
});

Cannot passing dynamically created image's ID and alert it

I am creating an image dynamically in Jquery and trying to add a control to it When the user clicks the image, I want to popup alert() with the image's id. But I couldnt succeed to show id of the image in the alert box. Please help me display the id of the image in alert box.
here is the code display the alert box
function category_follow(search_txt) {
alert(this.Attr('name'));
}
here is the code where I create the image dynamically
$.ajax({
url: 'HoverCard_WebService.aspx?q=' + encodeURIComponent(span_text),
type: 'GET',
dataType: 'json',
beforeSend: function () {
$(".hovercard").prepend('<p class="loading-text">Yükleniyor...</p>');
},
success: function (data) {
$(".hovercard").empty();
$.each(data, function (index, value) {
var search_txt = 'TestArif4';
result += '<div><button class=\'takibe_al\' name=\'test_name\' id=\'btn_test_id\' onClick=category_follow(\'' + value.id + '\')><img id=\'img_category_follow\' src=\'images/hover_card_plus_icon.png\' class=\'hover_cursor_hand\' /></button></div>';
});
},
What are you doing with your "result" variable?
function category_follow(search_txt) {
alert(this.Attr('name'));
}
this refers to the DOM Element and "Attr" should probably be "attr" if you are using jQuery.
I recommend you to use jQuery to bind your events instead of using the element attribute onClick;
$(document).on('click', '.takibe_al', function(event) {
var $this = $(this);
alert('Clicked on element with name = ' + $this.attr('name'));
});
See on.

How to fire click event on pressing enter Jquery-UI autocomplete

I have following JS:
$("#search").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/GetCompanyNames",
dataType: "json",
data: "searchterm=" + request.term,
success: function (data) {
response($.map(data, function (item) {
return {
label: item.Name,
value: item.Name,
LogoUrl: item.LogoUrl,
InternetName :item.InternetName,
Name: item.Name
};
}));
}
});
},
minLength: 1
}).data("autocomplete")._renderItem = function (ul, item) {
var innerHtml = '<div class="image" style="float: left; margin-right: 35px;"><img src="' + item.LogoUrl + '"></div><div class="label">' + item.Name + '</div></div>';
return $("<li></li>")
.data("item.autocomplete", item)
.append(innerHtml)
.appendTo(ul);
};
});
which renders this
This is a suggestion dropdown which shows when I enter any character in textbox like ib in this case,
Everything is working fine but there is only one problem when I click any item of dropdown with mouse it take me to the url which is written in its anchor tag, I want that if I scroll down with and press enter on some item it will do the same currently it's not doing anything when I press enter on a item of dropdown.
Take a look at this jqFAQ.com topic, this will help you to navigate to the url on selection made by both mouse click and pressing enter. There are few more autocomplete related FAQs too.
Try adding a keyup handler to the a element in your returned list items. You should be able to do that by modifying the _renderItem function:
._renderItem = function (ul, item) {
var div = $('<div />'), //building using DOM elements, rather than HTML string.
liContainer = div.clone().addClass('list_item_container').css('height', '60px'),
img = $('<img />').attr('src', item.LogoUrl),
imgContainer = div.clone().addClass('image').css({
"float": "left",
"margin-right": "35px"
}),
divLabel = div.clone().addClass('label').text(item.Name),
a = $('<a />').attr('href', '/Store/' + item.InternetName);
imgContainer.append(img);
liContainer.append(imgContainer).append(divLabel);
a.append(liContainer);
a.on('keyup', function (e) { //add keyup handler to navigate to new URL on [Enter]
if (e.which === 13) {
window.location.href = $(this).attr('href');
}
});
return $("<li></li>")
.data("item.autocomplete", item)
.append(a)
.appendTo(ul);
};

Categories