I am currently adding flagging functionality to a project of mine, and I can't get jQuery's $(this) selector to work.
The goal of this is to change the text in the div from flag to flagged when the user clicks it, and the ajax query runs successfully. My HTML/PHP is:
<div class="flag" post_to_flag='".$post_to_flag."'>Flag</div>
And my javascript that deals with the div is:
$('.flag').live('click', function () {
$.post('../php/core.inc.php', {
action: 'flag',
post_to_flag: $(this).attr('post_to_flag')
}, function (flag_return) {
if (flag_return == 'query_success') {
$(this).text('flagged');
} else {
alert(flag_return);
}
});
});
I can't replace the text with flagged, but if I replace the this selector with the .flag selector, it will replace everything with the class of flag on the page.
I have checked, and the $(this) selector is getting the attribute of 'post_to_flag' just fine. Why is this happening, and how can I fix it?
You should add a context variable:
$('.flag').live('click', function () {
var $context = $(this);
$.post('../php/core.inc.php', {
action: 'flag',
post_to_flag: $context.attr('post_to_flag')
}, function (flag_return) {
if (flag_return == 'query_success') {
$context.text('flagged');
} else {
alert(flag_return);
}
});
});
You are calling multiple functions within your jQuery selection call. When you go into that $.post() function, your scope changes. this now refers to a different scope from when you were inside one().
#Moak's suggestion, if you set a variable to a jQuery object, it's probably best to denote the variable with a beginning $ just for potential clarity for future readers or yourself.
this inside the ajax callback is not the element, but it is the Ajax object itself.
You can use $.proxy to pass in the context.
Ref $.proxy
$('.flag').live('click', function () {
$.post('../php/core.inc.php',
{action: 'flag', post_to_flag: $(this).attr('post_to_flag')},
$.proxy(function(flag_return) {
if(flag_return == 'query_success'){
$(this).text('flagged'); //Now this here will represent .flag
}else{
alert(flag_return);
}
},this)); //Now here you are passing in the context of `.flag`
Related
I'm trying to please JSLint's desire not to use this except in special cases. I have an original function, like this:
$.fn.extend({
my_original_function: function ([arguments]){
[arbitrary routine]
}
});
...called like this on an ID selector:
$('#my_id').my_original_function([arguments]);
In my original version of the function, I used this within it to return the selected DOM element on which the function is operating. However, JSLint doesn't like it, and so I'm trying to find a way to reference #my_id (in this example), which the function is being called on, within the function...without using this!
This seems like more of an academic exercise than anything, but I'm scratching my head on how I could retrieve the id within the function without using this. Any ideas?
* THE FUNCTION IN QUESTION *
It's a toggle function for switching text links when they are clicked. Here's the original version with this:
$.fn.extend({
toggleText: function(open, close) {
var isClicked = false;
var that = $(this);
$(this).click(function () {
if (isClicked) {
that.text(open);
isClicked = false;
} else {
that.text(close);
isClicked = true;
}
});
return $(this);
}
});
$('#id_one').toggleText("Toggle Text 1", "Toggle Text 2");
$('#id_two').toggleText("Hello", "Goodbye");
$.fn.extend({
toggleText: function(open, close, that) {...
$('#id_one').toggleText("Toggle Text 1", "Toggle Text 2", $('#id_one'));
I'm trying to call a function and not the alert and I thought it was as easy as just doing something like this: FunctionsName(); and delete the alert(''); but it's not working for me :(
Can someone please look at the code I have below and tell me what is wrong ?
Thank you so much!!
<script type="text/javascript">
var comper;
function checkComper() {
var onResponse = function(comperNow) {
if (comper === undefined) {
comper = comperNow;
return;
}
if (comper !== comperNow) {
// show a message to the visitor
alert("New Info Added"); // <--*** I WANT TO TAKE THIS OUT AND CALL $("#append").click(function(e)
comper = comperNow;
}
};
$.get('getlastupdate.php', onResponse);
}
var tid = setInterval(checkComper, 2000);
$(function() {
var $table = $("table.tablesorter");
$("#append").click(function(e) {
e.preventDefault();
$.get('updatetable.php', function(data)
{
$table
.find('tbody')
.html('')
.append(data);
$table.trigger("update", [true]);
});
});
/*........ and so on.... */
</script>
What about changin that :
alert("New Info Added");
to that :
$('#append').trigger('click');
It will simulate a click and trigger the function.
One thing important to distinguish:
alert("New Info Added") is a function. Actually, alert() is a function, being passed the parameter "New Info Added".
$('#append').click(function(e) { is not a function, at least, not in the same way. $('#append') is a jQuery selector function, which selects all elements with an id of "append". $('#append').click() is a function that sets a click event on all elements returned in the selector.
What the whole syntax of $('#append').click(function(e) { means is on its own a syntax error. What you're doing is telling the elements found in the selector what their click function should be. But the function(e) { says that it's the start of the code of the function. That line of code isn't complete until the ending }) - the } closing the function declaration and the ) closing the call to click.
So, you can't simply replace alert("New Info Added"), which is a complete function call, with $('#append').click(function(e) {, because it's a syntax error - you haven't completed the function(e) declaration, nor the click function call. You can trigger the click function, as Karl's answer told you. Or, you can use the shortcut:
$('#append').click()
Note that this is a full proper sentence, and can therefore replace the alert.
I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});
$(document).ready(function() {
$("#register button[name=btnPosta]").click(function() {
console.log('clicked');
thisBtn = $(this);
parent = $(this).parent();
name = parent.data('name');
$(this).attr('disabled', true);
$.post('register.php', {
name: ('name')
}, function(data) {
console.log('Ajax success');
parent.next('#message').html(data);
thisBtn.attr('disabled', false); // reset });
console.log('Ajax success');
});
});
});
This function is used to display name in the #message div
however nothing gets displayed in the div.
Assuming your markup is similar to the markup you posted in your duplicate post from an hour ago:
...
<tr>
<td> <td>
<td> <button class='regular' id = "btnPost" name='save'> Log In </button></td>
</tr>
...
The problem is in your use of .next(). When you pass a selector argument to .next(), you only get a result if the next sibling element matches the selector. Your call to parent.next("#message") returns an empty jQuery object because:
The next sibling of the button's parent element (which is the <td>) does not have an id of message.
Actually, there is no next sibling of that <td>.
Since parent.next("#message") returns an empty jQuery object, calling .html() on it has no effect. The solution is just to use $("#message") directly:
$('#message').html(data);
My original answer was just a red herring:
Make sure to use the var keyword when defining your variables. Without var, you are creating a property on the Global object (or window when running JavaScript inside a browser). But, parent is already a property of window. In IE, window.parent is read-only, so your value is never set and you will get an error when you call parent.data().
Your code works for me when I use var: http://jsfiddle.net/gilly3/MkS9X/
$(function() {
$("#register").find("button[name=btnPosta]").click(function() {
console.log('clicked');
//notice the use of `var` to keep the variables local, which will be faster
var thisBtn = $(this),
parent = thisBtn.parent(),
name = parent.data('name');
//notice the use of `.prop()` instead of `.attr()`, `.prop()` is new as of jQuery 1.6, so if you are using an older version then `.attr()` is the way to go
thisBtn.prop('disabled', true);
$.post('register.php', {
name: name //notice here that this references the `name` variable set further up
}, function(data) {
console.log('Ajax success');
parent.next('#message').html(data);
thisBtn.prop('disabled', false); // reset });
console.log('Ajax success');
});
});
});
Just a couple suggestions for your code. Mainly the variables were being created in the global scope for most likely no reason.
$('div#Settings ul li').click(function () {
var url, template;
var self = $(this);
if (!$(self).hasClass('selected')) {
var ContextMenu = CreateContext($(self));
var id = $(self).attr('id');
etc...
function CreateContext(item) {
var ContextMenu = $('div#ContextMenu');
if (!$(ContextMenu).length) {
$('<div id="ContextMenu"></div>').appendTo('body');
CreateContext(item);
}
$(ContextMenu).slideUp(150, 'swing', function () {
$(ContextMenu).insertAfter(item);
});
$(item).addClass('selected').siblings().removeClass('selected');
return $(ContextMenu);
}
On the first call to CreateContext(item) I cannot use the variable ContextMenu later in the .click code. However, if CreateContext is called twice, everything works fine. I am getting an undefined variable when i console.log(ContextMenu) the first time. The second time it gets the object correctly. How can I fix this? Thanks.
That's because div#ContextMenu doesn't exist the first time you call CreateContext. In fact your function detects that condition and then creates it. But, after creating it, you don't populate the value of ContextMenu inside your function so the rest of the function doesn't work properly.
Here's what I would suggest:
function CreateContext(item) {
var ContextMenu = $('#ContextMenu');
if (!ContextMenu.length) {
ContextMenu = $('<div id="ContextMenu"></div>');
ContextMenu.appendTo('body');
}
ContextMenu.slideUp(150, 'swing', function () {
ContextMenu.insertAfter(item);
});
$(item).addClass('selected').siblings().removeClass('selected');
return ContextMenu;
}
Note, once ContextMenu is a jQuery object, you don't have to surround it with $() after that as it's already a jQuery object.
Try taking the jQuery indicator out of your function. Since you've declared the variable as a jQuery object, I don't believe you need to identify it as a jQuery object AGAIN in your function.