Stop propagation in fullcalendar select callback - javascript

I'm developing a calendar using Fullcalendar (docs)
When an empty time slot is selected i want to show a context menu, like this:
(don't mind the styling)
select: function(start, end, jsEvent){
$("#calendarContextMenu").css({
display: "block",
left: jsEvent.pageX + 4,
top: jsEvent.pageY - 16
});
}
And hide it when anything else is clicked:
$(document).click(function(){
$("#calendarContextMenu").hide();
});
jsFiddle
This works well, but when an allday time slot is selected the context menu doesn't show up. I noticed this happens because $(document).click() is fired directly after fullcalendar's select callback. What can i do to fix it? It seems like there's some sort of event bubbling going on. Ofcourse, alternate solutions are always welcome.
Note: There is a div .fc-content-skeleton which is causing the problem i think.

I updated your codes and added the eventClick listener. Kindly check here: http://jsfiddle.net/e6v3mkjo/4/
Update 1:
Changed eventClick to dayClick
http://jsfiddle.net/e6v3mkjo/5/
Kindly check their docs as well: http://fullcalendar.io/docs/
Update 2:
Haha, I realized I didn't understand the question well. The solution to your real problem is just simple: remove the document click handler and then add the unselect handler.
unselect: function() {
$("#calendarContextMenu").hide();
}

Try:
$(document).click(function(){
console.log('hide');
$("#calendarContextMenu").show();
});

Related

Why does the select2-removing event not trigger in select2 with allowClear?

I want to hook an event in my select2 once it gets cleared. The select2 was initalized with allowClear: true. Yet the event
$select.on('select2-removed', function(event) {
console.log(event);
});
does not trigger when resetting the select2 with the clear button.
select2 v4.0.3
$('#smartsearch').on('select2:unselecting', function (e) {
alert('You clicked on X');
});
For all the select2 Options & Events
For me the only thing that worked is the 'select2:unselect' event... (In non-multiple select box)
According to the select2 source code, the clear method use the event select2-clearing instead of select2-removing. So you should listen to this event too.
select2-clearing and select2-removing are triggered before the removal. select2-removed is triggered after.
Keep in mind that clear does not always trigger the select2-removed event. It look like this event is triggered only if an element is actually removed from the input.
I got it working with the 'select2-removed'-event instead of 'select2-removing' when using the clear button.
As to why it does not trigger still eludes me.
I wanted to get data about the element just got removed on removed event. Following code worked for me;
$('#selector').on('select2:unselect', function (e) {
var data = e.params.data;
});
If you are working with 4 or above version then use
$('#id').on('select2:unselecting', function (e) {
alert('You clicked on X');
});
Below 4 version
$('#id').on('select2-removing', function (e) {
alert('You clicked on X');
});
Make sure for 4 or above version it is select2:unselecting colon(:)
Less than 4 version it is select2-removing -(hyphen)

JQuery-UI Datepicker() click event seems to conflict with a custom event

I'm a bit confused by some behavior on the frontend. Im using the datepicker() method from the JQuery UI libraries, and when a date is first selected, I want the calendar to slide left to display the rest of a form. That works fine unless the previous/next month elements are clicked first. Then the DOM changes(possibly unrelated) and nothing else happens. The calendar stays in its original position and the form never shows up. It's like the event listener that I wrote is being overridden. I'm assuming I just have a fundamental misunderstanding of event handling with javascript/jquery. Im a backend developer with only the slightest frontend experience, so if anyone could explain to me what im doing wrong, I'd be greatly appreciative.
Here's a super simplified example that creates the same behavior:
HTML:
<div id="calendar"></div>
CSS:
#calendar {
position:relative;
left:10em; }
JS:
$(document).ready(function () {
$("#calendar").datepicker();
$("#calendar tbody td").click(function () {
$("#calendar").animate({
left: "-30px",
easing: 'swing'
});
});
});
And here is a fiddle: http://jsfiddle.net/HM9ea/
Try this with onSelect:
$("#calendar").datepicker({
onSelect: function () {
$(this).animate({
left: "-30px",
easing: 'swing'
});
}
});
Demo
Issue with your code is that you were trying to animate a object which was not presenet at the state of document ready. so your event does not get fired, instead you can use the builtin method of select onSelect.

jQuery-UI tooltip shows after second mouseover

I have this piece of code:
(...)
if (data.hasSentMessages === true){
$("#sentMessages")
.parent()
.removeClass("ui-state-disabled");
} else {
$("#sentMessages")
.parent()
.addClass("ui-state-disabled");
}
And then, if element has disabled class, I want to show why is element disabled in jQuery-UI Tooltip. But unfortunately it shows after second mouseover event.
When I read this: Tooltip not showing on first mouseover I create something like this:
$("#sentMessages").tooltip({disabled: !($("#sentMessages").parent().hasClass("ui-state-disabled"))});
if($("#sentMessages").data("tooltip") === false){
$("#sentMessages").tooltip({disabled: !($("#sentMessages").parent().hasClass("ui-state-disabled"))}).triggerHandler("mouseover");
}
This condition, if widget is not initialized, should manually triggered mouseover event but unfortunately still it isn't working.
I will be very happy if somebody wants to help me - thank you in advance.
There is a simplified Fiddle: jsFiddle that shows a problem, there you can see that second tooltip is good but first is like ,,standard" browser tooltip.
In your fiddle, the initialisation of the tooltip happens within the mouseover callback function. This will mean that the tooltip is not created until after the first mouseover event.
Secondarily the mouseover event is built into the way that the jQueryUI tooltip functions. As such, you can remove the mouseover code.
Thirdly, you had mentioned that the tooltip should only display when the parent element has the class ui-state-disabled.
See the result on JSFiddle.
// construct a tooltip for each sentMessages then listen for the
// tooltipopen event an evaluate if it should show the tooltip
// or not
$("#sentMessages").tooltip().on('tooltipopen', function(){
if ($(this).parent().hasClass('ui-state-disabled')){
$(this).tooltip("enable");
} else {
$(this).tooltip("disabled");
}
});
// comment out this line to replicate a non error state
$("#sentMessages").parent().addClass("ui-state-disabled");
I hope this helps.
based on your example fiddle: add e.stopImmediatePropagation() to the mouseover event, see updated fiddle:

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.

check for ('div')mouseenter on ('a')mouseleave

my problem is following:
I got a trigger(a) and a popup(div). The div doesn't lie nested inside the anchor.
When I hover over a, I want the div to show up.
When I go from a to the div, I want it to stay visible.
When I leave the div, I want it to close.
When I hover over a and leave without entering the div, I want the div to close.
I got most of that figured out, but now I'm struggeling with requierement no. 2.
When checking for mouseleave on a, I check if there is a mouseenter on the div. If it is, I want to abort the mouseleave. If not, I want to close the div.
What am I doing wrong? Is this even the right way to do this?
Here's the markup:
<a href="#" class="popup_toggle" style='display:block;width:50px;height:50px;border:1px solid red;position:relative;'>Toggle</a>
<div class="popup_div" style='position:absolute;top:50px;left:0px;border:1px solid blue;display:none;'>Popup</div>
Here's the jQuery:
$('.popup_toggle').mouseenter(function() {
var element = $(this).next('.popup_div');
$.data(this, 'timer', setTimeout(function() {
element.show(100);
}, 500));
});
$('.popup_toggle').mouseleave(function() {
clearTimeout($.data(this, 'timer'));
if($('.popup_div').mouseenter==true)
{
return false;
}
else
{
$('.popup_div').hide(100)
};
});
What you're trying to do is fairly simple. When entering the trigger, identify the panel (layer, popup, whatever), save reference to each other using .data() and have the event handlers check if the related targets are either the trigger (from the panel view) or the panel (from the trigger view). I threw something together. Have a look at the console log to see how this works… http://jsfiddle.net/rodneyrehm/X5uRD/
That will most likely not work...no. I would suggest that you add a mouseenter and mouseleave callback to you <div> element as well and have them set a global variable that tells your other callbacks how to handle their events, i.e. "if global variable is true, don't hide the popup on mouseleave, otherwise hide popup" or something like this.
The other approach would be to check whether the mouse is inside the popup when the mouseleave callback tries to hide the popup. That might be much more work than it is worth though.
I believe the problem with your implementation is that the mouseenter on the div will fire shortly after the mouseleave from the a.
This would give you something like:
$('.popup_toggle').mouseenter(function() {
// Clear any pending "hide" timer
// Set a show timer
});
$('.popup_toggle').mouseleave(function() {
// Clear any pending "show" timer
// Set a hide timer
});
$('.popup_div').mouseenter(function() {
// Clear any pending "hide" timer
});
Note that you'll have to make sure that you access the same timer from both the .popup_toggle event and the .popup_div event. You may want to consider using Ben Alman's doTimeout plugin to help with this. It (usually) results in much clearer code than manually working with setTimeout/clearTimeout.

Categories

Resources