Select2 on elements loaded with JQuery - javascript

I'm using select2 on a project, and is working as it should, initiating the select2 using:
$(function() {
$(".elegible").select2();
});
The issue comes in when I'm trying to call de function to elements loaded by JQuery, I don't know how to call that function. I've tried "on" but it does not load the selects with the select2. The only thing I found is this:
$(document).ajaxComplete(function(e, xhr, settings){
$(".elegible").select2();
});
But this calls that function every time an ajax call is completed, even in those cases when I'm not needing the select2. My question is: How can I call the select to on elements loaded later? Is the method that I'm using right now valid? Can I improve that?
Thanks!
Adding Info:
I call the new content by getting it from another page - which loads the select - using ajax:
$.get('detalle_miembro/' + this.id)
.done(function(result) {
$('#detalle_miembro').html(result);
});
And placing it, in a div: <div id="detalle_miembro"></div>

Here is how you can call select on just the new content added:
$.get('detalle_miembro/' + this.id).done(function(result) {
$('#detalle_miembro').html(result).find(".elegible").select2();
});

Related

Prevent Ajax from triggering jQuery script

We got a simple jQuery script on Drupal site that injects a div class with content:
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
//code starts
//change placeholder text
$('.form-item-quantity').append('<span class="help-block">For orders over 10 call for volume pricing</span>');
$('.help-block').css("flex-basis", "100%");
//code ends
}
};
})(jQuery);
The page has Drupal Commerce and various product attribute fields that gets processed by Ajax every time selecting an attribute. And when doing that our script injects same duplicate line each time on Ajax load/update.
How to avoid that? We just want jQuery code work once on page load.
Only add the element if it doesn't exist, otherwise do nothing.
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
if (!document.getElementById('help')) {
$('.form-item-quantity').append(
'<span id="help" class="help-block">For orders over 10 call for volume ricing</span>'
);
$('.help-block').css("flex-basis", "100%");
}
}
};
})(jQuery);
You have to understand that drupal.behaviors fire on page load and when ajax returns results. It is designed this way because you may want your code to run again on the ajax results, for example, if you are updating part of the page via ajax and it needs event listeners applied, or a class added.
The context variable is the key here.
on first page load, the context will be the whole window, but when ajax returns the result, the context will just be what is returned by the ajax.
Knowing this, you should be using context in your jquery selectors.
eg.
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
//code starts
//change placeholder text
$('.form-item-quantity', context).append('<span class="help-block">For orders over 10 call for volume pricing</span>');
$('.help-block', context).css("flex-basis", "100%");
//code ends
}
};
})(jQuery);
For added protection against something processing multiple times, you can use jquery once(), but this is usually not needed if using the context variable in the selector. jQuery once() separate library that must be loaded.
Why don't use jQuery once? My thought — it's a classic approach. A bunch of examples lives in docs on drupal.org
$('.form-item-quantity').once('help-appended').append('<span class="help-block">For orders over 10 call for volume pricing</span>');
And I'm not sure you need to apply styles via js. A css file is a better place for it. And jquery once should be available in your environment. That's it.

have function work after div content is updated

I have a div with content in it. When the page loads, this function works fine. But when I update the div with content using javascript, this function fails to work.
Can anyone help me figure out what I should do to make this work?
$("textarea.indent").each(function(){
var indentWidth = $(this).siblings('[class=indent]').width();
if(indentWidth != null)
$(this).css('text-indent', (indentWidth+5)+'px');
});
Are you loading $("textarea.indent") dynamicly?
Jquery binds all events on document ready ie. when the page loads. That means that elements added after the page is done loading won't get bound to that event. To fix this you need to dynamicly bind your events as well. Like this..
$.ajax{
...
//Some ajax call
success: function(){
//Bind event
$("textarea.indent").each(function(){
var indentWidth = $(this).siblings('[class=indent]').width();
if(indentWidth != null)
$(this).css('text-indent', (indentWidth+5)+'px');
});
}
}
It doesn't have to be a ajax request thats add the elements, but my point still stands.

Binding jquery-multifile to a dynamically loaded form

I am using the jquery multifile plugin found here:
http://www.fyneworks.com/jquery/multiple-file-upload/
I've used it in the past and had no problems, but now I am trying to use it in a dynamically loaded form and it's causing a strange issue.
I am binding the function correctly when loading the form as per this article, so please understand this is a DIFFERENT, albeit related, problem to the one posted here:
Cannot bind input event to jQuery multifile from dynamically loaded form
$('#reportWindow').on('click', '#continueReport', function () {
var data = $('.reportForm').serializeObject();
$('<div/>').load('/Forms/report.aspx', data, function () {
doReportForm(this);
});
});
An ASPX file is being loaded into a div using jquery load as per the above, the doReportForm function is to call in various binding methods to that dynamically generated HTML as per:
function doReportForm(ele) {
$(ele).makeModal('', 800);
FB.XFBML.parse();
checkLogin();
clearNetIds($('#reportForm2'));
$("#datePicker").datepicker({
changeMonth: true,
changeYear: true
});
$('[class*="toolTip"]').setupTip();
$(".multi").MultiFile(); // input[type=file]
$('#right').on('click', '#savePost', function () {
var data = $('.reportForm2').serializeObject();
});
};
The first line there, $(ele).makeModal('', 800); is simply a jQuery extension I made to create modal windows, so it as it THIS point where the element is added to the DOM, then a few lines down I bind the MultiFile plugin thus $(".multi").MultiFile();
The first time this is done, it works fine. But, when a user closes the modal window and then tries to load the form again I get an error.
Uncaught TypeError: Cannot call method 'apply' of undefined
(closing the modal window removes it completely from the DOM with jQuery.remove(), so any future windows are written completely from fresh).
After a bit of fiddling, it appears that this is due to jQuery not being able to access the MultiFile script... I think
The MultiFile script is loaded in the head of the parent document, so should be available at all times.

Wrapping all AJAX calls jQuery

I populate many parts of my website using
$("#theDivToPopulate").load("/some/api/call.php", callBackToBindClickEventsToNewDiv);
Where /some/api/call.php returns a built list, div, or some other HTML structure to place directly into my target div. The internet has been running slow lately and I've noticed that the time between a button click (which kicks off these API calls) and the div populating is several seconds. Is there an easy way to globally wrap all the load calls so that a div containing "Loading..." is displayed before the call is even made and hidden once the API call is complete.
I can not simply put the code to hide the div into the callBackToBindClickEventsToNewDiv as some load events have different call backs. I would have to copy the code into each function which is ugly and defeats the purpose. I want the flow of any .load to go as follows:
1) dispplayLoadingDiv()
2) Execute API call
3) Hide loading div
4) do callback function.
The loading div must be hidden first as the callback contains some animations to bring the newly loaded div in nicely.
EDIT:
Expanding on jacktheripper's answer:
var ajaxFlag;
$(document).ajaxStart(function(){
ajaxFlag = true;
setTimeout(function (e) {
if(ajaxFlag) {
hideAllDivs();
enableDivs(['loading']);
}
}, 500);
}).ajaxStop(function(){
ajaxFlag = false;
var load = $("#loading");
load.css('visibility','hidden');
load.css('display','none');
load.data('isOn',false);
});
This way loading is only displayed if the page takes more than 500 MS to load. I found the loading flying in and out real fast made things kind of choppy for fast page loads.
Use the following jQuery:
$(document).ajaxStart(function(){
$('#loader').show();
}).ajaxStop(function(){
$('#loader').hide();
});
Where you have an element called #loader that contains what you want to show when an AJAX request is being performed. It could be a span with text, an image (eg a gif), or anything similar. The element should be initially set to display: none
You do not even need to call the function anywhere else.
Try this
$("#someButtonId").click(function(e){
e.preventDefault();
$("#theDivToPopulate").html("Loading...");
$.get("/some/api/call.php",function(data){
$("#theDivToPopulate").fadeOut(100,function(){
$("#theDivToPopulate").html(data).fadeIn(100,function(){
//Do your last call back after showing the content
});
});
});
});

f:ajax and jquery's `$(document).ajaxStart` dont work together?

I'm trying to get a 'loading' div for my ajaxified website.
using JSF 2.0's f:ajax tag for adding ajax to the website and 'trying' to make the loadin div show using jQuery $(document).ajaxStart function.
The jQuery code part looks like this:
$(document).ajaxStart(function(){
console.log("ajax start");
$('#ajaxBusy').show();
}).ajaxStop(function(){
console.log("ajax end");
$('#ajaxBusy').hide();
});
The log functions are never called.
Any Idea why? Do JSF ajax and javascript ajax not work together?
Thanks!
You should use jsf.ajax.addOnEvent(callback) to display a loading div. Maybe addOnError too.
See the documentation
jsf.ajax.addOnEvent(statusUpdate);
...
var statusUpdate = function statusUpdate(data) {
...
}
You will need to work with data.status
begin: before the request is sent
complete: request recieved
success: request succesfully processed (without errors)
Examples using this api:
http://weblogs.java.net/blog/driscoll/archive/2009/10/19/request-aggregation-jsf-2-ajax
http://weblogs.java.net/blog/driscoll/archive/2009/05/jsf_2_ajax_even.html
The shorthand $ can be the problem if using jsf, component libraries and jquery.
Try to call jQuery this way:
jQuery(document).ajaxStart(function(){ ... });
That's correct. Different JSF implementations may use different AJAX engines, and the jQuery ajaxStart/ajaxStop only apply to those components that route AJAX requests through the jQuery $.ajax function.
In contrast, if you're using Primefaces, the jQuery ajaxStart/ajaxStop events will fire and the jsf.ajax.onEvent will not fire.

Categories

Resources