jQuery tooltip: Trouble with remove() - javascript

I'm using a jQuery tooltip plugin.
I have HTML like this:
<li class="term ui-droppable">
<strong>Fall 2011</strong>
<li class="course ui-draggable">Biological Statistics I<a class="remove-course-button" href="">[X]</a></li>
<div class="term-meta-data">
<p class="total-credits too-few-credits">Total credits: 3</p>
<p class="median-GPA low-GPA">Median Historical GPA: 2.00</p>
</div>
</li>
I want to remove the .course element. So, I attach a click handler to the <a>:
function _addDeleteButton(course, term) {
var delete_button = $('[X]');
course.append(delete_button);
$(delete_button).click(function() {
course.remove();
return false;
}).tooltip();
}
This all works fine, in terms of attaching the click handler. However, when course.remove() is called, Firebug reports an error in tooltip.js:
Line 282
tsettings is null
if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
What am I doing wrong? If the link has a tooltip attached, do I need to remove it specially?
UPDATE: Removing .tooltip() solve the problem. I'd like to keep it in, but that makes me suspect that my use of .tooltip() is incorrect here.

I had this same issue and ended up having to delay the call of .remove() to prevent the error. So something like the following may work for you:
$(delete_button).click(function() {
setTimeout( function() { course.remove() } , 1);
return false;
}).tooltip();

The .tooltip() plugin has several handlers that attach to the element, namely on mouseover, mouseout, and click. If you're removing the element, just .unbind() all these events so they don't run, like this:
delete_button.click(function() {
course.unbind().remove();
return false;
}).tooltip();
One other change to note is that delete_button is already a jQuery object, wrapping it in $() again just clones it :)
The error happens because it's trying to fetch and use it's settings data off the element after it's been though .remove() via jQuery.data(), in which jQuery removes it's data from the cache. This approach this just prevents all those tooltip handlers from running again, so it won't matter that the data's gone (as it should be), because nothing will be looking for it now.

Related

JQuery Mobile vclick event only fires once

I'm trying to do a simple button rollover, changing it's icon when it's vclicked, but really don't get why the vclick event is only fired once, can someone shed some light on this? I get the same result if I use "click" or attach the event directly to the button element.
JSFiddle at: http://jsfiddle.net/w7quoyn4/
$('#btnAddToCart').on('vclick', function () {
console.log("btnAddToCart vclick event fired");
if ($(this).attr('data-icon', "plus")) {
$(this).attr('data-icon', "minus").button().button("refresh");
} else {
$(this).attr('data-icon', "plus").button().button("refresh");
}
});
Thanks in advance :)
There are two issues in your code.
First, the conditional expression $(this).attr('data-icon', "plus") invokes the setter form of attr(), which will always return the jQuery object its is called on. Since objects are always true in a boolean context, your else branch will never be taken.
To fix that, you could invoke the getter form of attr() and compare the result:
if ($(this).attr("data-icon") == "plus") {
// ...
}
Then again, the calls to button() are the heart of the matter. The appropriate method to use would be buttonMarkup(), but it is deprecated since release 1.4 (and will be removed in 1.5).
The actual solution is to add and remove the appropriate classes yourself, as in:
$(document).on("vclick", "#btnAddToCart", function () {
console.log("btnAddToCart vclick event fired");
$(this).toggleClass("ui-icon-plus ui-icon-minus");
});
You can see the results in this updated fiddle.

Disabling element in jQuery

Okay so I want to click an item, then have that item become unclickable, and not execute the jQuery attached to it. I am currently using this
$(clicked_id).prop('disabled', true);
However that is not working.
Any help is much appreciated!
EDIT:
This is the HTML:
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this.id); ">
disabled is only for disabling input elements (and it doesn't change the clickability of the object -- just that the default animation isn't executed).
To make it so that the click event is removed from an object, use .off()
$(clicked_id).off('click')
But this only works if the onclick was added via jquery
Instead, you may do this:
$(clicked_id)[0].onclick=false
Since your handler is assigned as an attribute, you can just nullify the property for that event handler.
document.getElementById(clicked_id).onclick = null;
just make sure you don't have a leading # on the ID.
Or us jQuery like this:
$(clicked_id).prop("onclick", null);
Or you can pass the element itself instead of passing the ID.
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this); ">
And then change your function so that it receives the element instead of the ID of the element. Once you do that, you can access the element directly.
elem.onclick = null;
There is another solution:
function getCard(objId){
if( !($('#'+objId).attr('used') == '1') )
{
alert('Click is working for '+objId);
// do something
$('#'+objId).attr('used', '1');
}
}
Here is a working example:
http://jsfiddle.net/HqHut/

jquery - using event.stopPropagation()

When the document is ready, I'm fetching some datas from the server through post request and I'm filling it in the HTML as tags by append. When you click that tag, a comment textarea will be displayed. When you click in the document section, the textarea will be closed. The problem here is I can't enter the text in the textarea, when I click inside, it is hiding. I tried using event.stopPropagation() but no use.
Here is my jquery code:
$.post("/person/keywords/get/", function(data){
for(i=0; i<data.length; i++)
{
count = count + 1;
$(".keywords-set").append('<div class="keyword-item"><span class="keyword" id="keyword-'+count+'">'+data[i]+'</span><textarea class="comment" id="comment-'+count+'"></textarea></div>');
}
});
$(".keywords-set").on('click', "[id^=keyword]", function(event) {
event.preventDefault();
i = $(this).attr("id");
i = i.split('-').pop();
$("#comment-"+i).show();
return false;
});
$(".comment").click(function(event) {
event.stopPropagation();
});
$(document).click(function() {
$(".comment").hide();
});
For complete HTML and javascript code, please check here: https://gist.github.com/3024186
It is working in jsfiddle
but not in my localhost. Could you tell the reason, why is it so?
Thanks!
UPDATE
I've also tried this
$(".keywords_set").on('click', ".comment", function(event) {
event.stopPropagation();
});
event.stopPropagation() is not working for HTML elements updated through ajax. But is working for normal(already given) elements.
When doing this:
$(".keywords_set").on('click', ".comment", function(event) {
You must understand that you're catching the event in the element ".keywords_set", and there you will be checking if it bubbled up through ".comment"
This means that any other "click" events set between ".keywords_set" and ".comment" will also activate.
doing stop propagation or returning false will only take affect from the bubbling of ".keywords_set" to the document.
You can do this:
$(document).click(function() {
if($(".comment:hover").length==0){
$(".comment").hide();
}
});
Edit: reply to: "Hey, that code works, I don't know how you are doing it by mentioning .comment.length could you be more descriptive about that?"
When you do any jquery selector, an array is returned. so if you do $(".comment") all html nodes with the class ".comment" will be returned to you in a list [obj1, obj2, ..., objn]
When you do $(".comment:hover") you are asking jquery to select you any element with the class "comment" which also have the mouse currently on top of it. Meaning if the length of the list returned by $(".comment:hover") is bigger than zero, then you caught a bubble from a click in a ".comment".
Although either returning false or stoping propagation should also work. (dunno why in your case it is not working, although i didn't look much at the full code)
Edit 2:
i was lazy to read the full code. but when you are setting the click event for the comment, the comment doesn't exist yet. so the new comment you are adding will not be be caught by your click handler. add it inside the ajax callback and it will work :)
Edit 3: one more thing:
you are not getting side effects because the click even you are re-defining only has the the stop propagation, but you should add the stop propagation before returning false in the
$(".keywords_set").on('click', ".comment", function(event) {
because in practice all other comments you have will be proccessing N times the click event that you are adding to be processed multiple times
Since post method is a asynchronous. You are binding $(".comment") before it exist.
moving
$(".comment").click(function(event) {
event.stopPropagation();
});
after
$(".keywords-set").append('<div class="keyword-item"><span class="keyword" id="keyword-'+count+'">'+data[i]+'</span><textarea class="comment" id="comment-'+count+'"></textarea></div>');
should work.

How can I call a Jquery method on DOM elements that don't exist yet?

I'd like to use this lightbox plugin for some autocomplete links, that don't yet exist on my page.
You normally activate it using:
$(document).ready(function($) {
$('a[rel*=facebox]').facebox()
})
Since the a links aren't all on the page upon page load, I would normally look to the .live or .delegate methods to bind to an event, but in this case, what 'event' would I bind to to say "once this element is on the page, then call this method on it".
Or am I going about this totally the wrong way?
There is no such event.
You need to invoke the plugin when you add the elements to the page.
// create a new <a>, append it, and call the plugin against it.
$('<a>',{rel:"facebox"}).appendTo('body').facebox();
This example creates a new <a> element. If you're getting some elements from an AJAX response, call it against those:
var elems = $( response );
elems.filter( 'a[rel="facebox"]' ).facebox(); // if the <a> is at the top level
elems.find( 'a[rel="facebox"]' ).facebox(); // if the <a> is nested
elems.appendTo('body');
Not yet tested :
$(document).ready(function($) {
$(document).bind('change', docChanged) ;
})
function docChanged()
{
if ($('a[rel*=facebox][class!="faceboxed"]').length > 0)
{
$('a[rel*=facebox][class!="faceboxed"]').addClass("faceboxed").facebox();
}
}
This is entirely possible using the .live function. You just need to use the DOMNodeInserted event.
$(document).ready(function() {
$("a[rel*=facebox]").live("DOMNodeInserted", function() {
$(this).facebox();
});
});
You'll need to just add this call to the ajax that loads in the links.

jquery tipsy plugin

Tipsy jquery plugin is installed in my app
This is in my load function
$(function() {
tipsy();
});
Below code is in a js file
var htm = '<div id="new_div" onmouseover="tipsy(this);">' ;
function tipsy(tip)
{
if ( '' != sumtitle )
{
tip.title = tip.innerHTML;
}
else if(tip)
{
tip.title = tip.innerHTML;
}
$(tip).tipsy({gravity: 'w'});
}
How is that the normal title shows up first and then the jquery tip later.
This is a known bug and will be fixed in the next version. For now please use the "Download Source" link on this commit:
http://github.com/jaz303/tipsy/commit/88923af6ee0e18ac252dfc3034661674b7670a97
The tipsy plugin seems to remove the title attribute and assign its value to a custom attribute called original-title to avoid the default browser tooltip from showing. Maybe in your case, this happens too late: The mouse hovers over the element, this initiates the native browser tooltip. Then, tipsy() is executed on the element and switches the attribute name, but that is too late because the timeout for the native tooltip has already started.
You should probably prevent the default action of the event, for example:
$('#new_div').bind('mousover', function (e) {
tipsy(this);
e.preventDefault();
});
EDIT: As this does not seem to have the desired effect, please call tipsy($('#new_div')) right after the div is created and remove the mouseover handler. What you have been doing might be a bit problematic anyway: The tipsy plugin probably uses the mouseover event, and you call .tipsy( { gravity: 'w' } ) in an onmouseover event handler. Repeatedly, if you mouseout and then mousover again. That's a lot of unnecessary event assignments.
You're doing it wrong.
Try this:
$('#new_div').tipsy();
jQuery is designed for using the selectors in JS code. No onsomething events in HTML, please.
Another way is, instead of using the 'title' attribute, use 'original-title' attribute.

Categories

Resources