The proper way to use siblings in jquery? - javascript

I am having an ajax function that returns updated value from the database. It is implemented under the click event of a certain button.
DIV :
<div class="rep">
<div class="up_arrow"></div>
<div class="rep_count"></div>
</div>
There are about 10 same divs repeating on a page. up_arrow is where the user will click.
I am trying to update the data in rep_count and also change the class of up_arrow to up_arrowed.
SUCCESS Function of Ajax :
success: function(data){
$(this).addClass('.up_arrow').removeClass('.up_arrowed');
$(this).css('background-position','0 40px');
$(this).next('.rep_count').html(data);
}
This success function is a part of ajax function which is invoked on a click function and thats the reason i'm using this to refer to its siblings. This is not doing what i'm expecting. I tried using siblings instead of next but that too is not doing the magic.
Thanks for your help in advance.
EDIT :
The Click function :
$('.up_arrow').each(function() {
$(this).click(function(event) {
var resid = $(this).attr('name');
var post_data = {
'resid' : resid,
'<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
};
if(resid){
$.ajax({
type: 'POST',
url: "/ci_theyaw/restaurants/plusrepo",
data: post_data,
success: function(data){
//console.log($(this).siblings('.rep_count').text());
$(this).addClass('.up_arrow').removeClass('.up_arrowed');
//$(this).css('background-position','0 40px');
//$(this).next('.rep_count').html(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
console.log(xhr.responseText);
alert(thrownError);
}
});
}
});
});

this inside the success handler does not refer the same object as it was referring outside the ajax call.
One solution is to use a closure variable self which is referring the clicked element and then use it in the success handler. Also there are few other changes
//there is no need to use .each() here
$('.up_arrow').click(function () {
var resid = $(this).attr('name');
var post_data = {
'resid': resid,
'<?php echo $this->security->get_csrf_token_name(); ?>': '<?php echo $this->security->get_csrf_hash(); ?>'
};
var self = this;
if (resid) {
$.ajax({
type: 'POST',
url: "/ci_theyaw/restaurants/plusrepo",
data: post_data,
success: function (data) {
//console.log($(this).siblings('.rep_count').text());
//you had swapped the class names here also should not use . in front of the class name, it is used only for class selector
$(self).addClass('up_arrowed').removeClass('up_arrow');
//$(this).css('background-position','0 40px');
//$(this).next('.rep_count').html(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
console.log(xhr.responseText);
alert(thrownError);
}
});
}
});
Another solution is to use $.proxy as shown below to pass a custom context
success: $.proxy(function(data){
$(this).addClass('.up_arrow').removeClass('.up_arrowed');
$(this).css('background-position','0 40px');
$(this).next('.rep_count').html(data);
}, this)

You need to pass the item the user clicked on to the success function. I would change your code to this:
$('.up_arrow').click(function() {
//you don't need an .each() loop to bind the events
var TheClickedItem = $(this);
.......
success: function(data){
//now you're accessing/modifying the item that was actually clicked.
TheClickedItem.addClass('.up_arrow').removeClass('.up_arrowed');
TheClickedItem.....
}

The problem is that this does not refer to the clicked element inside the success callback.
Use the context option in $.ajax to specify what you need as this inside the success callback.
$.ajax({
...
context: $(this), // now the clicked element will be `this` inside the callback
...
success: function(data) {
// here 'this' refers to the clicked element now
},
...
});

You need to save this in onclick context, because in ajax-success function this refers to other context. You should do something like this:
$('.up_arrow').on('click', function() {
var self = this; // save this refering to <a>
$.ajax(.....,
success: function() {
// this - refers to success-function context, but self - refers to 'a'-onclick handler
$(self).addClass('.up_arrow').removeClass('.up_arrowed');
$(self).css('background-position','0 40px');
$(self).next('.rep_count').html(data);
}
)
})

Related

How to bind button function to a corresponding item in an array - AJAX, Firebase

I'm attempting to first make an AJAX request from a social API and append the results with a button inside the div that will save the corresponding item in the array to my firebase database. For example,
I have my AJAX request - I cut out about 75% of the actual code that isn't needed for the question.
$.ajax({
type : 'GET',
url : url,
dataType : "jsonp",
cache: false,
success : function(data){
console.debug(data);
vids = data.response.items;
for(var i in vids) {
dataTitle = vids[i].title;
ncode = "<div class='tile'><img src='"+ vids[i].title "'/></a><button class='btn' type='button' onClick='saveToDatabase()'>Save</button></div>";
$('#content').append( ncode )
And then I have my function that I want to save the 'title' of the object the button was appended with to the firebase database.
var dataTitle;
function saveToDatabase() {
ref.push({
title: dataTitle
});
}
The issue is that when the button is clicked it posts a random title from inside the array instead of the title of the item the button was appended with... How can I bind the buttons function to the correct dataTitle?
I'm not sure if that makes sense so please let me know if clarification is needed. Thanks in advance for any help you can provide!
This fails because you are iterating the entire list and assigning them to a global variable. The result is not random at all--it's the last item in the list, which was the last to be assigned to the globar variable.
Try using jQuery rather than writing your own DOM events, and utilize a closure to reference the video title.
function saveToDatabase(dataTitle) {
ref.push({
title: dataTitle
});
}
$.ajax({
type : 'GET',
url : url,
dataType : "jsonp",
cache: false,
success : function(data) {
console.debug(data); // console.debug not supported in all (any?) versions of IE
buildVideoList(data.response.items);
}
});
function buildVideoList(vids) {
$.each(vids, function(vid) {
var $img = $('<img></img>');
$img.attr('src', sanitize(vid.title));
var $button = $('<button class="btn">Save</button>');
$button.click(saveToDatabase.bind(null, vid.title));
$('<div class="tile"></div>')
.append($img)
.append($button)
.appendTo('#content');
});
}
// rudimentary and possibly ineffective, just here to
// point out that it is necessary
function sanitize(url) {
return url.replace(/[<>'"]/, '');
}
I actually just ended up passing the index to the function by creating a global array like so. It seems to be working fine... any reason I shouldn't do it this way?
var vids = []; //global
function foo() {
$.ajax({
type : 'GET',
url : url,
dataType : "jsonp",
cache: false,
success : function(data){
console.debug(data);
vids = data.response.items;
for(var i in vids) {
ncode = "<div class='tile'><img src='"+ vids[i].title "'/></a><button class='btn' type='button' onClick='saveToDatabase('+i+')'>Save</button></div>";
$('#content').append( ncode )
} //end ajax function
function saveToDatabase(i) {
ref.push({
title: vids[i].title
});
}

Function Statements no name error

I have the following code:
<script type="text/javascript">
$(document).on("click", "#leftconversation", function(){
var self = this;
var cid = $(this).attr('class'); // getting the user id here
var request = $.ajax({
url: "conversation.php",
type: "POST",
data: { cid: cid },
beforeSend: function(){
self.html("Loading please wait...");
}
});
//WHEN SUCCESS
request.success(function( data ) {
$("#right").html(data); // replace the right div with echoed content from php file
});
});
</script>
However, my console keeps giving me the error: “SyntaxError: Function statements must have a name.”
I can't seem to fix the issue and that’s why the AJAX code isn’t running. Where’s this error coming from?
As per what Todd said, i changed the code to following:
<script type="text/javascript">
$(document).on("click", "#leftconversation", function(){
var self = this;
var cid = $(this).attr('class'); //you are getting the user id here
var request = $.ajax({
url: "conversation.php",
type: "POST",
data: { cid: cid },
beforeSend: function(){
self.html("Loading please wait...");
},
success: function(data) {
$("#right").html(data);
},
error: function(request, err){ console.log('An Error Occured' + err); }
});
});
</script>
It fixed the first error, but now its telling me TypeError: undefined is not a function (evaluating 'self.html("Loading please wait...")')
This is fixed, should have used var self = $(this); instead
as per my comment
$(document).on("click", "#leftconversation", function(){
var $self = $(this);
var cid = $(this).attr('class'); // getting the user id here
var request = $.ajax({
url: "conversation.php",
type: "POST",
data: { cid: cid },
beforeSend: function(){
$self.html("Loading please wait...");
}
});
//WHEN SUCCESS
request.success(function( data ) {
$("#right").html(data); // replace the right div with echoed content from php file
});
});
You can fix your issue without having to use a variable. Just set the context: property of the $.ajax call.
var request = $.ajax({
url: "conversation.php",
type: "POST",
data: { cid: this.className }, // Quicker way to get the class.
context: $(this), // The context in the callback will be the jQuery object.
beforeSend: function() {
// v-- This is now a jQuery object.
this.html("Loading please wait...");
}
});
Your code, as you have posted it, is correct. The error must be coming from elsewhere. That said, wherever the error is, here’s what to look for:
As you likely know, functions can be defined like this:
function greet(name) { /* ... */ }
This works in a statement context. Functions can also be used in an expression context:
[1, 2, 3].forEach(function(item) { alert(item); });
In an expression context, we can omit the name, as we did above, or we can include a name:
[1, 2, 3].forEach(function foo(item) { alert(item); });
However, what we cannot do is have a standalone function declaration without a name. This is an error:
function(name) { /* ... */ }
That is what your (now first) problem was.
“undefined is not a function”
Your updated code has a different problem. When you set self = this, this is a DOM element, not a jQuery object. You later try to use self.html, but DOM elements do not have a html property. If you wish to use jQuery methods, you must convert the element into a jQuery object, either at the point of assignment (self = $(this)) or at the point of use $(self).html.

Firebug: TypeError: 'click' called on an object that does not implement interface HTMLElement

I get this Error when I click the button with the ID "#123" - I don't know what's the reason for this.
Code in my PHP File:
$("#123").click(function(){
getCheckedValues('oberpunkte', 'input:checkbox[class=oberpunkte]:checked', 'input[type=textfield]');
getCheckedValues('unterpunkte', 'input:checkbox[class=unterpunkte]:checked', 'input[type=textfield]');
ajaxCheckedValues('POST', 'selected.php', '#sumadd');
});
My JS Functions for the Code above:
function getCheckedValues(arrayname, selector, nextselector){
var array = arrayname;
array = new Array();
$(selector).each(function(){
array.push($(this).next(nextselector).val());
});
}
function ajaxCheckedValues(type, url, div){
var kategorie = ($("input:radio:checked[name='kategorie']").attr('class'));
$.ajax({
type: type,
url: url,
data: { oberpunkte : oberpunkte, unterpunkte : unterpunkte, kategorie : kategorie },
success: function (data)
{
console.log(data);
$(div).html(data);
}
});
}
Firebug Error:
I also alerted "kategorie" - it's not null. Any ideas?
HTML/PHP of Button and DIV:
echo("<input type='button' name='test' id='123' value='Checklist speichern'/>");
echo("<div id='sumadd' value=''></div>");
EDIT NOTE: Added HTML/PHP
I guess that problem is because you were getting undefined on oberpunkte and unterpunkte in ajax call. Try this
$("#Button123").click(function(){
var oberpunkte=[], unterpunkte=[];
getCheckedValues(oberpunkte, 'input:checkbox[class=oberpunkte]:checked', 'input[type=textfield]');
getCheckedValues(unterpunkte, 'input:checkbox[class=unterpunkte]:checked', 'input[type=textfield]');
ajaxCheckedValues('POST', 'selected.php', '#sumadd',oberpunkte,unterpunkte);
});
function getCheckedValues(array, selector, nextselector){
$(selector).each(function(){
array.push($(this).next(nextselector).val());
});
}
function ajaxCheckedValues(type, url, div,oberpunkte,unterpunkte){
var kategorie = ($("input:radio:checked[name='kategorie']").attr('class'));
$.ajax({
type: type,
url: url,
data: { oberpunkte : oberpunkte, unterpunkte : unterpunkte, kategorie : kategorie },
success: function (data)
{
console.log(data);
$(div).html(data);
}
});
}
Also change the id of input field. Id must start with alphabet .
Check
What are valid values for the id attribute in HTML?

Jquery .ajax passing msg to click event

I'm developing a small application in javascript using jquery but i've a small problem.
i've this function
function cercahq(urlvalue) {
$.ajax({
type: "POST",
url: "data.php",
data: "do=urlget&url=" + urlvalue,
dataType: "html",
success: function(msg) {
var data = eval('(' + msg + ')');
$("#searchbar").css({'background-color': '#C33'});
// creates element
var insertform = document.createElement('form');
insertform.id = "insertform";
var insertbutton = document.createElement('button');
var insertbuttonlabel = document.createTextNode('Insert');
insertbutton.appendChild(insertbuttonlabel);
insertform.appendChild(insertbutton);
$("#searchbar").append(insertform);
$(insertbutton).click(function(event, data) {
event.preventDefault();
alert(data.title);
});
stampa(msg)
},
error: function()
{
alert("Error");
}
});
}
This function gets json data from a php script and pass it to a function (stampa) that evals it and print it in the page, but i need to create a button outside the stampa function that tells me a value from the json...
So inside the success event i've insered another eval to grab the ajax msg and create the variable data that should be passed to a button element that i've created inside a form called insertform.
The point is: how to pass the "data" variable to the click function from an element created inside an ajax request success function?
The 'data' variable should be accesible inside click function through closure, no need to pass it there. By passing it as parameter you override it as closure with 'undefined' value. So just remove it from parameters:
$(insertbutton).click(function(event) {
event.preventDefault();
alert(data.title);
});

jQuery ajax success doesn't work with $(this)?

Ive been playing with the ajax tools in jQuery and am having an issue with using $(this) inside the success of the execution of my ajax. I was wondering if its possible to use $(this) inside of your success as ive seen tutorials use it but when i attempt to use it it doesnt work... However if i use $(document) or some other method to get to the object i want it works fine... Any help would be greatly appreciated as i am quite new to jQuery! Thanks in advance! The code im playing with is as follows:
$(".markRead").click(function() {
var cId = $(this).parents("div").parents("div").find("#cId").val();
var field = "IsRead";
$.ajax({
type: "POST",
url: "ajax/contract_buttons.php",
dataType: "text",
data: "contractId=" + cId + "&updateField=" + field,
async: false,
success: function(response) {
//$(this) doesnt recognize the calling object when in the success function...
$(this).find("img").attr("src", "images/read.png");
},
error: function(xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
alert(thrownError);
}
});
});
this always refers to the current execution context so it does not necessarily stay the same in a callback function like an ajax success handler. If you want to reference it, you must just do as Dennis has pointed out and save its value into your own local variable so you can reference it later, even when the actual this value may have been set to something else. This is definitely one of javascript's nuances. Change your code to this:
$(".markRead").click(function() {
var cId = $(this).parents("div").parents("div").find("#cId").val();
var field = "IsRead";
var element = this; // save for later use in callback
$.ajax({
type: "POST",
url: "ajax/contract_buttons.php",
dataType: "text",
data: "contractId=" + cId + "&updateField=" + field,
async: false,
success: function(response) {
//$(this) doesnt recognize the calling object when in the success function...
$(element).find("img").attr("src", "images/read.png");
},
error: function(xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
alert(thrownError);
}
});
});

Categories