I want to be able to run an anonymous function on specified future elements once they become part of the DOM. I couldn't find an answer to this. I need a cross-browser event that bubbles, and only runs once when the element is created, or ready, or something along those lines.
Internet Explorer has the "activate" event which is just what I need, except it is only in IE. I tried using the DOMActivate event in Chrome, but it behaves strangely when I tested it on a text input box. It would only fire when the element is clicked on, and it fired twice in a row. It acted like a focus event that is triggered twice, which is not helpful.
Here is an example of what I am trying to accomplish:
$('body').on('activate', '.date-picker', function () {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
$('body').on('DOMActivate', '.date-picker', function () {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
I realize I can accomplish this with future elements using a callback after I place them on the DOM, or by triggering my own event, but I was looking for a cleaner solution.
EDIT:
I got it to work like this:
$('body').on('activate', '.date-picker', function (e) {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
var activateSupported = 'onactivate' in document.documentElement;
if (!activateSupported) {
$(document).bind('DOMNodeInserted', function (e) {
var target = $(e.target);
target.trigger('activate');
target.find('*').trigger('activate');
});
}
This isn't really ideal as it has to make all those extra function calls in browsers other than IE. Anyone have better solutions?
Due to how this plugin works (it is not visible until you focus the input,) you can lazy-bind the plugin using event delegation.
$(document).on("focus", ".date-picker", function (e) {
e.preventDefault();
$(this).removeClass(".date-picker").datepicker({dateFormat: 'mm/dd/yy'}).focus();
});
The first time it is focused, it is initialized. After it is initialized, the focus event is re-triggered to cause the datepicker to open. By removing the .date-picker class, I prevent it from re-initializing the datepicker on subsequent focus events.
Related
I have an html text node (an li tag in this case) that I am trying to trigger focus on using jQuery:
$('#branch').focus();
Or even:
$('#branch').trigger('focus');
I have attached an event listener:
$('#branch').on('focus', function() { console.log('focused'); });
But the event listener isn't firing. What do I need to do to fire this event listener?
If I listen for a 'hocus' event, and fire that event instead, the listener does indeed fire:
(I need this to unit test what happens when you focus on the node, I'm building an accessible tree)
As detailed by Shane Tomlinson here:
Text nodes are considered to be inert, and therefore cannot be
"focused" according to the w3c
Firing jQuery's .focus() method on a text node basically just gets swallowed up.
Instead, you have to use vanilla JS (works in Chrome, haven't tested other browsers):
$('#branch').on('focus', function () {
console.log('jquery listened');
});
var branch = document.getElementById('branch');
branch.addEventListener('focus', function() {
console.log('js listened');
});
// $('#branch').focus(); // this doesn't work! Use JS below instead...
var event = new Event('focus');
branch.dispatchEvent(event);
See jsbin of example
I'm using Jquery UI datepicker for my Rails application, and I want to trigger an event whenever someone clicks on the button for next month. It is not triggering anything though. My JQuery version is v1.12.4.
Here's a sample of my html code:
<input type='text' name='date_from' class="form-control date_picker" placeholder="Data de ida..." id='datetimepicker1' required/>
<div id="datepicker1" class="calendar"></div>
The HTML code for the datepicker is the default generated by JQuery UI.
So here is my javascript attempt:
$('body').on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
});
It does nothing! It doesn't raise an error on the console, it doesn't print anything and it doesn't attach the click event to the elements with the ui-datepicker-next class.
If I copy and paste the following code in the console it works well for the current elements in the document.
$('.ui-datepicker-next').click(function(e){
console.log('Next/prev month')
e.preventDefault();
});
It has never happened to me before, so I'm sorry if this question should be more detailed, but I really don't know what else I should mention here.
Edit:
jsfiddle: https://jsfiddle.net/9484zzrL/
This is the best I could do so far to recreate the issue on jsfiddle.
If you click on a day of the selected month it is fine, but if you change the month it doesn't work anymore.
Edit 2:
I believe this recreates perfectly my problem. Simply the event is not triggered when I choose any date in the calendar.
https://jsfiddle.net/awhwr3uv/
Edit:
So I looked at your latest jFiddle. I wondered if you had tried to use something like this:
$("#datepicker1").datepicker({
firstDay: 1,
onSelect: function(date) {
console.log('Date Selected: ' + date);
//Do some other cool stuff here
$(this).hide();
}
});
$("#datepicker2").datepicker({
firstDay: 1,
onSelect: function(date) {
console.log('Date Selected: ' + date);
//Do some other cool stuff here
$(this).hide();
}
});
You can carry out everything you need to in the onSelect option that is in your jFiddle and it even passes you the date to the callback as an argument.
Original
Change this:
$('body').on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
To this:
$(document).on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
It works in your fiddle.
Edit
I wanted to explain my guess at why your code didn't work.
I think it is because jQuery already has a click listener attached to the body element for the class of the button. Because 2 click listeners are attached to the body for the same class of element, the first one the JavaScript engine reaches is the one that fires.
In effect when you attach a click listener to the body using the on method the JavaScript engine is constantly scanning the body for clicks and then checking if the click matched your selector. Because jQuery already has the click listener on the body for that selector your listener never received the event.
With that in mind by attaching your click listener to the document, you have an entirely new listener set up and the engine is now also scanning the document for clicks and seeing it matches your selector. Because yours is the only one listening on the document yours gets the event.
So I tested this by changing the listener from click to mouseover and sure enough it works.
$('body').on('mouseover','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
I hope this helps. It's the best I can come up with as to why your code didn't work.
I have kind of strange problem.
I'm trying to add a couple of events to som DOM elements (all existing, some initially hidden:
$self.on("focus", function () {
$self.next().css("display", "inline-block");
});
$self.on("blur", function () {
$(this).next().hide();
});
$self.parent().find(".icon-ok").on("click", function() {
console.log("icon.ok")
});
You can see the relevant part of the DOM here (self is the span user-name):
Later on, the element eventually because visible and I can click on it. However, the event handler is never called. If I remove the blur event, than the click event works. However, I need both.
What's going on here?
How can I fix it?
Looks like the blur cancels out the click (due to event order) but using mousedown instead of blur may help you get both.
UPDATE: Added code based on comment
$self.parent().find(".icon-ok").on("mousedown", function() {
console.log("icon.ok")
});
Your problem might be the classic delegation problem, where in the element is not available in the DOM when the event is bound.
Delegate the event and see if that solves your problem.
$self.on("click", ".icon-ok", function() {
console.log("icon.ok")
});
User $self if that element is visible or any closest ancestor that you can find which is always present in the DOM.
I have a Timer in javascript that's doing stuff in the background every xxx seconds. however the ajax work in the background seems to interrupt the users typing. I fix this by disabling the timers when focus/blur like one would, however, how can i make this site wide?
I want a way to magically detect any focus/blur events happening in any inputbox/textarea element and call some code, for both blur and focus.. is there a way to achieve this that will work without individually settings up the handlers for each of them?
You may try something like this:
$('input, textarea').on({
focus: function(e) {
// ...
},
blur: function(e) {
// ...
}
});
If you want same function for both events then (probably you don't want this):
$('input, textarea').on('focus blur', function(e) {
// ...
});
I am using a jQuery DateTimePicker addon (By: Trent Richardson) and it will only close after you select the date AND the time. However some users don't care about the time and they want the Calendar to close after they choose the date only.
I managed to close the Calendar after picking the Date only but I need to implement a double click and not a single click. How do I do that?
Here is my code:
$(jqCompletedEndID).datetimepicker({
ampm: true,
onSelect: function(){
$(this).datepicker("hide"); $(this).blur();
}
});
I know there is a dblclick event in Javascript but not sure how to apply it in this context.
Thank you!
I have run into the exact same problem / requirement. I tried something very similar to Alex's solution, but it doesn't work because the datetimepicker seems to wipe all styles and event bindings when a day is selected (I assume it's being reconstructed, but haven't checked), making it impossible for the dblclick event to fire.
I've come up with a solution which isn't pretty but does work. You can use the datetimepicker's onSelect event to bind a couple of handlers as follows:
(assuming this._$input is a jQuery reference to the input control being used)
this._$input.datetimepicker({
...
onSelect: function() {
var self = this;
setTimeout(
function () {
$('.ui-datepicker-current-day').bind('click', function () { self._$input.datepicker('hide'); });
$('.ui-datepicker-current-day').bind('dblclick', function () { self._$input.datepicker('hide'); });
},
0
);
}
You're probably wondering why I bind both click and double click, particularly in light of my claim above that double click won't work. It seems that in Chrome, FireFox, Safari, and Opera the event will trigger the "click" event, but in IE it will trigger the "dblclick" event. Also, if you're wondering about the setTimeout, it's required because the popup won't be constructed until after the method is finished, so those selectors won't return anything if executed without it.
You've no doubt noticed that my solution will also close the picker when the currently-selected date is clicked whether or not it's part of a double-click. This is intentional in my case (and I also trigger the same logic in the beforeShow event to wire the handler so clicking on the currently-selected date will always close the picker). In your case, if you want it to work strictly with double clicks, all I can recommend is that you track the time between clicks and make sure they arrive within some threshold.
Try this...
$('#datepicker').datepicker({
//...
});
$('table.ui-datepicker-calendar a').bind('dblclick', function() {
$('#datepicker').val();
});
You can add a doubleclick event handler on the html tag itself. You would be having a emtpy div for the datepicker, so modify it as
<div id="datepicker" ondblclick="close()"></div>
In the close() function write the code to hide the datepicker div.