I have a jQuery plugin project, actually if it helps it's in github and you can see the full code at https://github.com/jondmiles/bootstrap-datepaginator/tree/1.2.0.
So I have an click event handler, one of the first things it does is use jQuery .closest to look up the DOM and find the parent anchor tag that the user has clicked. This is necessary as icons sit in front of some anchors and I want consistency in the element I'm handling.
Here's the code in question, line 273 of /src/bootstrap-datepaginator.js in the project if you want it in context.
_clickedHandler: function (event) {
event.preventDefault();
var target = $(event.target).closest('a');
var classList = target.attr('class') ? target.attr('class').split(' ') : [];
if (classList.indexOf('dp-no-select') !== -1) {
// do nothing
}
else if (classList.indexOf('dp-nav-left') !== -1) {
this._navBack();
}
else if (classList.indexOf('dp-nav-right') !== -1) {
this._navForward();
}
else if (classList.indexOf('dp-item') !== -1) {
this._select(target.attr('data-moment'));
}
},
Now I also have a datepicker (https://github.com/eternicode/bootstrap-datepicker) which is attached to an icon element, added during the rendering process.
It looks like this, line 476 in the project
if (this.$calendar) {
this.$calendar
.datepicker({
autoclose: true,
forceParse: true,
startView: 0,
minView: 0,
todayHighlight: true,
startDate: this.options.startDate.date.toDate(),
endDate: this.options.endDate.date.toDate()
})
.datepicker('update', this.options.selectedDate.date.toDate())
.on('changeDate', $.proxy(this._calendarSelect, this));
}
When the user clicks on the calendar icon the datepicker should appear. It used to, up until a recent change but now nothing happens; no calendar.
I've tracked the issue down to the addition of the .closest() method which was a recent addition. So it appears calling the .closest() on the event target some how suppresses the datepicker, but I can't figure out why, or how to work around this.
So to recap, when it worked line 275 looked like this
var target = $(event.target);
Now it doesn't work, line 275 looks like this
var target = $(event.target).closest('a');
Any ideas?
Related
I'd like to be able to use the arrow keys to get to the select2 option I want and then press tab to select that option and then tab to the next element as usual.
I already got the down arrow to open the select2 with the following:
$(document).on('keydown', '.select2', function(e) {
if (e.originalEvent && e.which == 40) {
e.preventDefault();
$(this).siblings('select').select2('open');
}
});
And I can also use the arrows to get where I need to go. Now I'm struggling to make the tab part work.
I'm assuming since the select2-search__field has focus at the time I'm pressing the key, that that is the element I bind the event to? And then presumably I need to get the value of the currently highlighted option and trigger the select2 change?
I'm not 100% sure this is the right approach but I can't quite figure it out.
To achieve this you can use selectOnClose: true:
$(document).on('keydown', '.select2', function(e) {
if (e.originalEvent && e.which == 40) {
e.preventDefault();
$(this).siblings('select').select2('open');
}
});
$('select').select2({
selectOnClose: true
});
select {
min-width: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" />
<select>
<option>AAAAA</option>
<option>BBBB</option>
<option>CCCC</option>
<option>DDDD</option>
<option>EEEE</option>
<option>FFFF</option>
<option>GGGG</option>
</select>
Just add following line in your code.
$(document).on("select2:close", '.select2-hidden-accessible', function () { $(this).focus(); });
Your issue will be resolved.
I had this same issue. Because selectOnClose: true also means that pressing Esc or clicking outside of the select dropdown was selecting the input, I have opted for a far more complicated and less elegant solution than the accepted answer. My solution has solved this issue for me (and allows subsequent tabbing to switch focus on down the DOM).
I added a listener to select2:closing (which fires immediately before it closes and thus when the highlighted li is still highlighted). Select2 gives that li an id that contains the value of the option to which it's tied. I parse that out and squirrel it away in state (I'm using Vue):
$(this.subjectSelect2).on('select2:closing', () => {
var idArray = $(".select2-results__option--highlighted")[0].id.split("-");
var id = idArray[idArray.length - 1];
this.select2LastHighlighted = id;
})
I then added a listener for keydown, so that if tab is pressed, it takes that value from state, and updates the select2 to that value:
$(this.subjectSelect2).on('select2:open', () => {
$(".select2-search__field")
.on('keydown', (e) => {
if (e.key == 'Tab') {
this.subjectSelect2.val(this.select2LastHighlighted);
this.subjectSelect2.trigger('change');
}
})
})
I'd love to hear if someone has a more elegant way to do this!
I am trying to make function call on bootstrap datepicker when user clicks outside of calendar.
When user selects date datepicker closes automatically, same when user clicks outside of the datepicker div, it closes itself.
So my question is how can I understand when its closed? I know there is an event called onClose but it only works when page loads
fiddle
Use the .on("hide"... event.
From the docs:
$('.datepicker').datepicker()
.on(picker_event, function(e) {
// `e` here contains the extra attributes
});
For your example... picker_event will be hide.
Something like:
var checkin = $('#date-from').datepicker({
format: 'dd/mm/yyyy',
startDate: '+1d',
weekStart: 1,
beforeShowDay: function(date) {
return date.valueOf() >= now.valueOf();
},
autoclose: true
}).on('changeDate', function(ev) {
alert("changed");
}).on('hide', function(ev) { // <-----------
alert("hide");
});
Updated fiddle
bootstrap-datepicker events
bootstrap-datepicker hide event
As per the documentation here: https://bootstrap-datepicker.readthedocs.io/en/latest/events.html#hide
$('.datepicker').datepicker()
.on('hide', function(e) {
// `e` here contains the extra attributes
});
Or
$('.datepicker').datepicker()
.on('hide', myFunction);
And then create myFunction
function myFunction(e) {
// whatever you want :)
}
Here is your example with little modify https://jsfiddle.net/mr3dxj5p/6/ here you can see I just change changeDate to hide to fire alert message
<script type="text/javascript">
// When the document is ready
$(document).ready(function () {
$('.datepicker').datepicker({
format: "yyyy-mm-dd",
}).on('changeDate', function(ev){
// do what you want here
$(this).datepicker('hide');
}).on('changeDate', function(ev){
if ($('#startdate').val() != '' && $('#enddate').val() != ''){
$('#period').text(diffInDays() + ' d.');
} else {
$('#period').text("-");
}
});
});
</script>
So here's what my datepicker looks like. So basically when I change date by clicking mouse it works good, however when I manually change date with keyboard or manually clear the date change date event doesn't get called. Is this a bug or am I doing something wrong here ?
You have to use the change event on the input itself if you want to respond to manual input, because the changeDate event is only for when the date is changed using the datepicker.
Try something like this:
$(document).ready(function() {
$('.datepicker').datepicker({
format: "yyyy-mm-dd",
})
//Listen for the change even on the input
.change(dateChanged)
.on('changeDate', dateChanged);
});
function dateChanged(ev) {
$(this).datepicker('hide');
if ($('#startdate').val() != '' && $('#enddate').val() != '') {
$('#period').text(diffInDays() + ' d.');
} else {
$('#period').text("-");
}
}
In version 2.1.5
bootstrap-datetimepicker.js
http://www.eyecon.ro/bootstrap-datepicker
Contributions:
Andrew Rowls
Thiago de Arruda
updated for Bootstrap v3 by Jonathan Peterson #Eonasdan
changeDate has been renamed to change.dp so changedate was not working for me
$("#datetimepicker").datetimepicker().on('change.dp', function (e) {
FillDate(new Date());
});
also needed to change css class from datepicker to datepicker-input
<div id='datetimepicker' class='datepicker-input input-group controls'>
<input id='txtStartDate' class='form-control' placeholder='Select datepicker' data-rule-required='true' data-format='MM-DD-YYYY' type='text' />
<span class='input-group-addon'>
<span class='icon-calendar' data-time-icon='icon-time' data-date-icon='icon-calendar'></span>
</span>
</div>
Date formate also works in capitals like this data-format='MM-DD-YYYY'
it might be helpful for someone it gave me really hard time :)
The new version has changed.. for the latest version use the code below:
$('#UpToDate').datetimepicker({
format:'MMMM DD, YYYY',
maxDate:moment(),
defaultDate:moment()
}).on('dp.change',function(e){
console.log(e);
});
Try this:
$(".datepicker").on("dp.change", function(e) {
alert('hey');
});
I found a short solution for it.
No extra code is needed just trigger the changeDate event. E.g.
$('.datepicker').datepicker().trigger('changeDate');
Try with below code sample.it is working for me
var date_input_field = $('input[name="date"]');
date_input_field .datepicker({
dateFormat: '/dd/mm/yyyy',
container: container,
todayHighlight: true,
autoclose: true,
}).on('change', function(selected){
alert("startDate..."+selected.timeStamp);
});
This should make it work in both cases
function onDateChange() {
// Do something here
}
$('#dpd1').bind('changeDate', onDateChange);
$('#dpd1').bind('input', onDateChange);
Depending which date picker for Bootstrap you're using, this is a known bug currently with this one:
Code: https://github.com/uxsolutions/bootstrap-datepicker
(Docs: https://bootstrap-datepicker.readthedocs.io/en/latest/)
Here's a bug report:
https://github.com/uxsolutions/bootstrap-datepicker/issues/1957
If anyone has a solution/workaround for this one, would be great if you'd include it.
I have this version about datetimepicker https://tempusdominus.github.io/bootstrap-4/ and for any reason doesn`t work the change event with jquery but with JS vanilla it does
I figure out like this
document.getElementById('date').onchange = function(){ ...the jquery code...}
I hope work for you
I was using AngularJS and AngularStrap 2.3.7 and trying to catch the 'change' event by listening to a <form> element (not the input itself) and none of the answers here worked for me. I tried to do:
$(form).on('change change.dp dp.change changeDate' function () {...})
And nothing would fire. I ended up listening to the focus and blur events and setting a custom property before/after on the element itself:
// special hack to make bs-datepickers fire change events
// use timeout to make sure they all exist first
$timeout(function () {
$('input[bs-datepicker]').on('focus', function (e){
e.currentTarget.focusValue = e.currentTarget.value;
});
$('input[bs-datepicker]').on('blur', function (e){
if (e.currentTarget.focusValue !== e.currentTarget.value) {
var event = new Event('change', { bubbles: true });
e.currentTarget.dispatchEvent(event);
}
});
})
This basically manually checks the value before and after the focus and blur and dispatches a new 'change' event. The { bubbles: true } bit is what got the form to detect the change. If you have any datepicker elements inside of an ng-if you'll need to wrap the listeners in a $timeout to make sure the digest happens first so all of your datepicker elements exist.
Hope this helps someone!
if($('.single_datetime').length){
$('.single_datetime').dateRangePicker({ format: 'DD.MM.YYYY HH:mm', language: 'tr', autoClose: true, singleDate : true, showShortcuts: false, time: {enabled: true}
}).bind('datepicker-change',function(event,obj){caclDay();});
}
Ref: https://www.chamonix-property.com/bower_components/jquery-date-range-picker/
I have a span element that I want to become editable upon double-click. (That is, the user can edit the text and it will save when s/he clicks outside.)
The effect I want to emulate is similar to when I double-click CSS properties in the Google Chrome Developer Tools. (See picture.)
Now tested, and does work (at least Firefox 8 and Chromium 14 on Ubuntu 11.04):
$('span').bind('dblclick',
function(){
$(this).attr('contentEditable',true);
});
JS Fiddle demo.
Edited in response to Randomblue's comment (below):
...how do I detect when the user clicks outside the span, so that I can set attr('contentEditable', false)
Just append the blur() method:
$('span').bind('dblclick', function() {
$(this).attr('contentEditable', true);
}).blur(
function() {
$(this).attr('contentEditable', false);
});
JS Fiddle demo.
If you want a solution that works in ALL modern browsers, here's a nifty little jQuery plugin I made that emulates the functionality you described:
SIMPLY DROP THIS BLOCK INTO YOUR CODE-BASE:
//plugin to make any element text editable
//http://stackoverflow.com/a/13866517/2343
$.fn.extend({
editable: function() {
var that = this,
$edittextbox = $('<input type="text"></input>').css('min-width', that.width()),
submitChanges = function() {
that.html($edittextbox.val());
that.show();
that.trigger('editsubmit', [that.html()]);
$(document).unbind('click', submitChanges);
$edittextbox.detach();
},
tempVal;
$edittextbox.click(function(event) {
event.stopPropagation();
});
that.dblclick(function(e) {
tempVal = that.html();
$edittextbox.val(tempVal).insertBefore(that).bind('keypress', function(e) {
if ($(this).val() !== '') {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
submitChanges();
}
}
});
that.hide();
$(document).click(submitChanges);
});
return that;
}
});
Now you can make any element editable simply by calling .editable() on a jQuery selector object, like so:
$('#YOURELEMENT').editable();
To get the changes after the user submits them, bind to the "editsubmit" event, like so:
$('#YOURELEMENT').editable().bind('editsubmit', function(event, val) {});
//The val param is the content that's being submitted.
Here's a fiddle demo: http://jsfiddle.net/adamb/Hbww2/
The above works: I've tested it in this jsfiddle: http://jsfiddle.net/nXXkw/
Also, to remove the editability when user clicks off of the element, include:
$('span').bind('blur',function(){
$(this).attr('contentEditable',false);
});
I found this nice jQuery plugin: "X-editable In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery" http://vitalets.github.com/x-editable/
I found many answers to be out of date on this topic, but adamb's was the easiest solution for me, thank you.
However, his solution was bugged to fire multiple times due to not removing the keypress event along with the element.
Here's the updated plugin using $.on() instead of $.bind() and with the keypress event handler being removed when the element is created again.
$.fn.extend({
editable: function() {
var that = this,
$edittextbox = $('<input type="text"></input>').css('min-width', that.width()),
submitChanges = function() {
that.html($edittextbox.val());
that.show();
that.trigger('editsubmit', [that.html()]);
$(document).off('click', submitChanges);
$edittextbox.detach();
},
tempVal;
$edittextbox.click(function(event) {
event.stopPropagation();
});
that.dblclick(function(e) {
tempVal = that.html();
$edittextbox.val(tempVal).insertBefore(that).off("keypress").on('keypress', function(e) {
if ($(this).val() !== '') {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
submitChanges();
}
}
});
that.hide();
$(document).one("click", submitChanges);
});
return that;
}
});
http://jsfiddle.net/Hbww2/142/
I have a small jQuery script:
$('.field').blur(function() {
$(this).next().children().hide();
});
The children that is hidden contains some links. This makes it impossible to click the links (because they get hidden). What is an appropriate solution to this?
This is as close as I have got:
$('.field').blur(function() {
$('*').not('.adress').click(function(e) {
foo = $(this).data('events').click;
if(foo.length <= 1) {
// $(this).next('.spacer').children().removeClass("visible");
}
$(this).unbind(e);
});
});
The uncommented line is suppose to refer to the field that is blurred, but it doesn't seem to work. Any suggestions?
You can give it a slight delay, like this:
$('.field').blur(function() {
var kids = $(this).next().children();
setTimeout(function() { kids.hide(); }, 10);
});
This gives you time to click before those child links go away.
This is how I ended up doing it:
var curFocus;
$(document).delegate('*','mousedown', function(){
if ((this != curFocus) && // don't bother if this was the previous active element
($(curFocus).is('.field')) && // if it was a .field that was blurred
!($(this).is('.adress'))
) {
$('.' + $(curFocus).attr("id")).removeClass("visible"); // take action based on the blurred element
}
curFocus = this; // log the newly focussed element for the next event
});
I believe you can use .not('a') in this situation:
$('.field').not('a').blur(function() {
$(this).next().children().hide();
});
This isn't tested, so I am not sure if this will work or not.