Add jquery datepicker dynamically after page load - javascript

Upon a button click, I have some jquery that will add some html to the 'body' element. In that html, I have a datepicker input field which refuses to appear when it should.
I use the ui-datepicker in several other spots in my app, and it works perfectly.
I have tried calling the datepicker when the document loads:
jQuery ->
$('.my-datepicker-class').each ->
input = $(this)
input.datepicker()
and after the click event which adds the new html to the page:
$('.my-button').click ->
$('body').ipadoverlay
titleStyle: false
contentWidth: 500
topSpc: true
content: $('#popup-for-' + thing_id).html()
$('.my-datepicker-class').each ->
input = $(this)
input.datepicker()
But the picker refuses to show up. My guess is that it has to do with when jquery builds and places the datepicker, but I really don't know.
Let me know if you have any ideas or could use more information.
UPDATE
I changed the way I call datepicker() so that it only applies to the element I want the datepicker attached to.
$('.ipadoverlay .date-picker').datepicker()
This eliminates the first issue with the .each =>.
Now it silently fails. No error or warning. The datepicker simply does not show up.
I am going to begin digging into jquery.ui.datepicker.js to see if I can figure out whats going on, but if you have any ideas why the datepicker fails to response, please let me know.
UPDATE 2
Ok, I got a step further. The class 'hasDatepicker' was already attached to the element I want add the datepicker to (which means $('.date-picker').datepicker() was being called somewhere else, while the element was hidden and unused), but the datepicker didn't work. I fixed this by removing the class from my element, and calling .datepicker() again
$('.ipadoverlay .date-picker').removeClass('hasDatepicker')
$('.ipadoverlay .date-picker').datepicker()
Now the datepicker shows up on click, but selecting a date doesn't do anything... Help would be much appreciated

You need to use the fat arrow. Your use of 'this' loses its context.
jQuery ->
$('.my-datepicker-class').each => # <-- Fat arrow
input = $(this)
input.datepicker()
I'd explain, but coffeescript.org does a better job than I ever could.

Related

How do I destroy all instances of Bootstrap Popover?

I have a single page app using Backbone, and whenever I over over something and then click the "back" button, the popover forever stays.
I want to destroy all instances of popover when a new instance is loaded.
Finding the popovers that are created through the data API is not difficult and has been covered in other answers like those of David Mulder and Amir Popovich. You just do:
$("[data-toggle='popover']").popover('hide');
Or you can use destroy if you need to or prefer to.
The challenge is to handle those popovers that are created dynamically.
Marking the Elements with Popovers
I would implement something like this. I'd override the default popover method and I'd try to perform this override as early as possible so that everything that needs a popover uses my override. What it does is just mark elements that use a popover with a class. Bootstrap does not mark them itself:
// Override popover so as to mark everything that uses a popover.
var old_popover = $.fn.popover;
function my_popover() {
this.addClass('marked-as-having-a-popover');
return old_popover.apply(this, arguments);
}
$.fn.popover = my_popover;
Then to clear everything before the unloading, I'd put in the code that detects the unloading the following:
$(".marked-as-having-a-popover").popover('hide');
Or it could use destroy rather than hide if testing shows that it works better for your use-case.
Now, the method above will work if the override happens early enough and you do not have a page where multiple jQueries are loaded. (Yep, this is possible.) I use something similar to deal with tooltips in one of my applications so I know the principle is sound. It so happens that in my app, all tooltips are created by my code so there is no risk of missing something.
Finding All Elements with Popovers, Even Unmarked
If you are in a situation where a popover can be created without being marked (I call this an "escapee"), then you need to query the whole DOM and find which elements have popovers. There is no shortcut here. You cannot rely on attributes like data-content because popovers can be created wholly dynamically (i.e. without any of the data- attributes). Also, all kinds of elements can get popovers, so you cannot reliably assume that only button elements will have a popover. The only surefire way to find everything that needs handling is to look at each element in the DOM and check whether it has a popover:
// Obviously this is quite expensive but in a situation where there *can* be escapees
// then you have to check all elements to see if they have a popover.
$("*").each(function () {
// Bootstrap sets a data field with key `bs.popover` on elements that have a popover.
// Note that there is no corresponding **HTML attribute** on the elements so we cannot
// perform a search by attribute.
var popover = $.data(this, "bs.popover");
if (popover)
$(this).popover('hide');
});
Again, destroy could be used rather than hide.
Proof of Concept
Here is a fiddle that illustrates the entire thing:
"Add a Dynamic Popover" simulates code that would add a popover when the override is in effect.
"Add an Escapee" simulates code that would add a popover and somehow manage to use the original Bootstrap code.
"Clear Marked" clears only the marked popovers.
"Clear All" clears every single popover marked or not.
try with this:
$('YOUR_ELEMENT_SELECTOR').popover('dispose');
reference url: https://getbootstrap.com/docs/4.1/components/popovers/
Its very simple, just you have to call one function popover() with argument "destroy" to destroy the popover. It will destroy all popovers which is created by $("[data-toggle=popover]").popover();
you can check documentation for more options and arguments of popover().
I suggest you to destroy popovers with having specific class name instead of using following code.
$("[data-toggle='popover']").popover('destroy');
The above code will destroy all popovers in the page. So instead of this, use class selector.
$(".YourClassName").popover('destroy');
If you have problems and need to remove all for sure:
$('.popover').remove();
will help (Popover automatic add this class, even for dynamicly created objects). It destroys all the popover DOM-Object incl. callbacks, etc.
But thats the rough way. Typically I displose all by popover class (clean way) and to be sure I do a hard clean up after. Works for me fine!
$('.popover').popover('dispose');
$('.popover').remove();
If you like to remove all execpt one, use a filter() with :not-Selector
$('.popover').filter(':not(#yourID)').popover('dispose');
$('.popover').filter(':not(#yourID)').remove();
popover adds also a id with a random number
#popoverxxxxx where xxxxx is a five digit number.
this helps sometimes to compare popovers. Of cause this could also be used to identify the popovers.
Something generic like this (assuming you're using data-bindings) should do the trick:
$('[data-toggle="popover"]').popover('hide')
or the more extreme call
$('[data-toggle="popover"]').popover('destroy')
though I doubt that would make sense often. Still to address the specific bug you're encountering you should create a minimal test case so that that bug itself can be addressed.
Oh and if you specifically want to check for open popovers you can use .data("bs.popover").$tip.parent().length (which is a bit of an hack), for example:
$('[data-toggle="popover"]:eq(0)').data("bs.popover").$tip.parent().length == 1
You can hide all popovers by using this:
$("[data-toggle='popover']").popover('hide');
You can destroy all popovers by using this:
$("[data-toggle='popover']").popover('destroy');
The difference between hide and destory is that when you hide a popover you do not need to reactive it, but when you destroy it you do.
Check out my JSFIDDLE and then:
Click on all popovers and then click hide. After clicking hide you can click on the popovers again.
Click on all popovers and then click destroy. After clicking destroy try clicking on the popovers again and see that nothing will happen since they are destroyed. In order to make them functional again, you will need to click on reactive and then try.
Popovers must be initialized manually, so you know exactly what you have to destroy because you did initialize it.
You should just call the destroy function with the same selector.
Or maybe I am missing something ?

jquery-ui datepicker not appearing on dynamic input

I inherited a bunch of code of varying quality and I'm fixing a bunch of things that has been wrong. One thing that it does is that is has a table of form inputs, one of which uses jquery-ui Datepicker. There is also a button that creates a new row at the bottom of the table. The new row's Datepicker never shows up.
I've seen this problem listed a few times here on SO but none of those solutions worked. I'm putting up what I have now. My jfiddle is at:
http://jsfiddle.net/squarepegsys/G8WEC/2/
The meat of my code is here:
tr.find(".datepicker").on("focusin",function() {
console.log("got focus");
$(this).datepicker();
});
In the on("focusin"...) line, I see "got focus" on the console but never see the datepicker show up.
When you create the datepicker instance, jQuery assigns it an ID, and when you clone it, you're duplicating it. Instead, create the datepicker instance dynamically via:
$(document).on('focus', ".datepicker", function () {
$(this).datepicker( "destroy" ).datepicker();
})
jsFiddle example
This will work for dynamically created elements and jQuery will manage the IDs properly.

Datepicker initialization for class fields added after page load

I have fields where multiple extra fields can be added after the page loads (think education & work experience fields on job resumes). I am using this.
I can add a datepicker on the first field, but subsequent added fields do not access the datepicker, despite being cloned/essential duplicates of the original. I'm guessing that the datepicker only intializes on page load or for only one class on the page.
So on a page I initialize the datepicker:
$('.input-append.date').datepicker();
for a block of form code encapsulated by this class. OK for initial page load; and also OK if there is an error and the page reloads multiple fields previously input(there is a datepicker for all fields returned with any error). However, with another js function that adds new fields to the form, additional new fields do not have access to the datepicker. I do not see how to do this now, perhaps someone with more experience/wisdom can provide me a hint.
EDIT:
Simple enough: I simply added:
$('.input-append.date').datepicker();
to the code calling the new field. As to being the optimal solution I do not know, anyone who specializes in js can comment on that, and there are many other similar questions here I found once I expanded my search terms. However, good enough for me now in what I'm doing.
For elements which are being added on fly use data-provide="datepicker" attribute. It will be initialized lazily. For example if an input field is coming up in an ajax response and loaded in a container div. So in this case:
<input type="text" data-provide="datepicker" />
so when when you will load this ajax response it in cotainer div like
$('#container-div').html(ajax_response);
this will work.
In the same way if you are creating an element through jquery and appending it to some container (I think this is happening in your case), for example you have a function that creates textbox and append it to some container div and this function is called on click event of some element let's say it's button. Again data-provide attribute is the solution to this problem. For example
function createTextBox(){
var t = $('<input>').attr('data-provide','datepicker');
$('#container-div').append(t);
}
And this function is called on click event of some button like in this way:
$(document).ready(function(){
$('#someBtn).click(createTextBox);
});
In short whether that dynamic element is coming in ajax response as a string or being created through jquery, just use data-provide attribute to set bootstrap datepicker. Because in this case datepicker is initialized lazily in Bootstrap fashion.

Extjs 4 how hide/show trigger on combox field without doComponentLayout?

I am need hide/show trigger on fields (combobox,*date* and etc.) without invoke method doComponentLayout() (source code of setReadOnly method). The method doComponentLayout() is very slowly on IE. Can anybody help me? Thank you!
You can also use the setHideTrigger(true) method. This is a private method on Ext.form.field.ComboBox - (see Extjs ComboBox, make sure to check "Private" in the "Show" menu.)
Calling myCombo.triggerEl.hide() doesn't work if the combo component hasn't been rendered yet.
You can also hide the trigger when component is first initialized by setting the config property hideTrigger: false.
You should be able to show/hide the triggerEl that is a property of anything that extends Ext.form.field.Trigger (such as combo, date, etc.).
See live example here:
http://jsfiddle.net/hWGYE/765/

jQuery UI Multiselect widget clear all check boxes

Hopefully a quick one...
I need to fire the uncheckAll event in the click event of a separate button on my page, I have tried the following:
$('.masterProviderOrgsListBox').multiselect().uncheckAll();
but this isnt a recognised method. I basically want to fire the same method that is fired when you click the "Uncheck All" box in the header.
I was previously doing this:
$('.masterProviderOrgsListBox option:selected').removeAttr("selected");
but this removes the selections on the actual multiselect rather than the jQuery UI widget.
Couldnt find anything in the documentation, any ideas?
Methods
After an instance has been initialized, interact with it by calling
any of these methods:
// example: $("#multiselect").multiselect("method_name");
...which can be found in the widgets documentation under Methods
$("#multiselect").multiselect("uncheckAll");
1) first, you need to set default value of the control.
jQuery('#multiselect').val("");
2) Then, execute below code to reset the control.
jQuery('#multiselect').multiselect("refresh");
$("#multiselectoption:selected").removeAttr("selected");
$("#multiselect").multiselect('refresh');
refresh should be call after clearing the drop down.

Categories

Resources