How to get reference to calling control in jquery.autocomplete function - javascript

I have an MVC page that contains multiple text entries. The controls on the page are all data driven. What I've done, is tag each of the autocomplete inputs with class="ACBox". They all have their own Ids. I have also added a custom attribute called fname, where fname is the field identifer. fname could be "size", "color", "connectionpoints", etc. (could be lots of these)
What I would like to do, is use one autocomplete function to make an ajax call to my controller with the fname of the control passed back to my function to return the appropriate list of possibles.
However, I do not find a way to get a reference to the calling object for autocomplete to read in the fname attribute. My current solution below, the pfield is Nothing when I examine in GetOptionsFromField.
Is there a way to set pfield? Optionally, I could use this.id to set as pfield.
$(".ACBox").autocomplete({
source: function (request, response) {
$.ajax({
url: "#Url.Action("GetOptionsFromField", "ControllerX")",
dataType: "json",
data: {
pfield: $(this).attr("fname")
},
success: function (data) {
response(data);
}
});
},
minlength: 5,
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});

Okay, It looks like I needed to search better. This was answered back in 2014, with this question.
I use
$(this.element).data("colname")
and it works like a charm.

Related

How to stop/pause async call of ajax

I am stuck on this since yesterday, now I need help. I don't know how to properly 'question' this, but I think this is around the concern of ajax is asynchronous.
I am unable to complete the ajax call from my view when I call an ajax function inside an ajax postback.
$.ajax({
url: '#Url.Action("GetValidateAssignAccountName", "AccountsAssignment")?companyID=' + companyid,
type: request_method,
data: form_data
}).done(function (data) {
if (data == '') {
PromptAssign(data, post_url, request_method, form_data);
}
else {
Assign(post_url, request_method, form_data);
}
});
Assign function doesn't work/complete. I don't know how to call it, but it goes through the controller and calls the stored procedure, returns a success msg, but for some reason, the procedure did not work/save.
My problem is that, when I call PromptAssign - in which case I call a messageDialog and then call the Assign inside, right there the Assign does the job. Here is the PromptAssign function:
$("#messagedialog").dialog({
open: function () {
$(".ui-widget-overlay").css({ background: "#000000", opacity: 0.5 });
$(".ui-dialog-title").css("color", "#228B22");
//$(".message-img").attr("src", "../Content/images/success.png");
$(".message-wrapper").html(msg);
},
modal: true, height: 250, width: 500,
buttons: {
//'Ok': function () { $(this).dialog('close'); },
'Assign': function () {
Assign(post_url, request_method, form_data);
$(this).dialog('close');
},
'Close': function () { $(this).dialog('close'); }
},
create: function () {
$(this).closest(".ui-dialog")
.find(".ui-button").eq(2)
.addClass("btn btn-default");
},
title: "Confirmation",
dialogClass: "noclose"
});
Initially, the code was just the assign function which calls an sp to save a data. But we added the PromptAssign (first code block, then call a msgbox/PromptAssign, then assign) which is a validation if its existing or not, then the user can still Assign after if he still chooses to.
So when the validation returns nothing, I don't need to PromptAssign, so I just call the Assign straight away. This is not working. Anything I am missing on how to use ajax?
Just to answer the comments, there was an earlier problem like this that goes to the ajax, and then to the controller executing the stored procedure but for some reason the data isn't updated. We fixed the issue by making those ajax calls in a separate function.
For this one, I was trying to apply the same thing to no avail, I know there is nothing wrong in my way of using ajax, turns out, it was a data issue. The specific record in which I was testing is not working properly due to database validations. Still, thank you for looking at it.

Why is my javascript function finding my checkbox to be false

My code looks something like this
HTML
<div><input type="checkbox" name="showInactiveBox" value="showInactiveBox" id="showInactiveBox">Show inactive project numbers</div>
Javascript
$("#showInactiveBox").live("click", function () {
if ($(this).is(":checked")) { //checkbox is checked
$.ajax({
type: "POST",
url: "#Url.Action("UpdateInactiveBox", "Project")",
data: {
showInactive: true
}
})
.done(function (data) {
Debug.writeln("Check box is checked?: " + $("#showInactiveBox").is(":checked"));
$("#project-numbers-grid").data("kendoGrid").dataSource.read();
});
I have an else that looks similar to above, just sets the checkbox to false basically. My debug line above in the .done of the Ajax function returns the correct value whether it be checked or not. However I then call the .read() on my grid which relates to more javascript below:
read: {
url: "#Html.Raw(Url.Action("GetActiveProjectNumbers", "Project"))",
type: "POST",
cache: false,
dataType: "json",
data: {
q: function () {
var model = {
projectid: "#Model.Id",
};
return JSON.stringify(model);
},
showinactive: $("#showInactiveBox").is(":checked")
}
},
When I put another Debug.writeline in the server, it is receiving the correct value for "q" but "showinactive" is always read in as false. Is there something with javascript that I don't quite understand where going from function to function will read a different value for ($"checkboxid").is(":checked")?
Thanks
Are you sure .is() works with the jQuery version you are running? You could also try .prop('checked'). I would try running this in the Chrome developer tools on the page:
$("#showInactiveBox").is(":checked")
and
$("#showInactiveBox").prop("checked")
If those return the value you are looking for, then there is something else going on. Try running those in console.log at the point at which you are calling those functions to see what the active output is:
console.log('This is my checkbox value', $("#showInactiveBox").is(":checked"));
In addition to Lawrence Johnson's (.prop) answer I'd take a look at some of the other code you are using.
For instance, when dealing with checkboxes it's always better to use the .change() method rather than click.
Also, the .live method is deprecated now and should be using .on().
When dealing with checkboxes you can easily use "vanilla javascript" to test if the box is checked or not. jQuery is not always the "less code/best solution".
See the below code for all the amendments mentioned above:
<input type="checkbox" name="showInactiveBox" value="showInactiveBox" id="showInactiveBox">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$('#showInactiveBox').on('change',function(){ //using .on and change rather than click
if ( this.checked ) {//test if checked or not
console.log('checked');
}
})
});
</script>
Change
showinactive: $("#showInactiveBox").is(":checked")
to
showinactive: function() {
return $("#showInactiveBox").is(":checked");
}
and call it with
showinactive()
Currently, you are setting showinactive to the value of the property, which I'm assuming starts as false. Values in javascript don't update with the DOM like that--you need to explicitly check each time.

jQuery plugin bsmSelect doesn't update its values when it is called again and its select options have changed

I'm using bsmSelect jQuery plugin. Basically, what it does is changing the way a select-multiple is rendered to make easier to pick up the options. It hides the select element and shows a list instead.
So, first of all I'm applying the plugin function to my select-multiple element:
$(document).ready(function() {
...
$('#my_select_multiple').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
...
});
On the other way, I have another select element (this one is simple) which has an ajax request bind to its change event. This ajax request get new #my_select_multiple options depending on the select simple value. Ajax response is the new HTML for #my_select_multiple options. So I have:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/
}).responseText;
return r;
}
...
$(document).ready(function() {
...
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val()));
}
...
});
AJAX is working as expected. New options are got correctly and they are inserted into #my_select_multiple (which is hidden by bsmSelect plugin, but I can check it with Firebug). But bsmSelect didn't realize new changes and doesn't get updated.
So, I think what I want is to reapply $('#my_select_multiple').bsmSelect(); with its new options.
I've been looking around a little bit and here is what I have tried.
1. I've tried to call again the funcion with the success and complete (one at time) of the AJAX request. Didn't work:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function() { $('#my_select_multiple').bsmSelect(); }
}).responseText;
return r;
}
2. I've tried to bind the function with the on jQuery function. Didn't work:
$('#my_select_simple').on('change', function() {
$('#my_select_multiple').bsmSelect();
});
3. I've tried 1 and 2 removing previosly the HTML generated by bsmSelect. Didn't work.
Thank you very much.
UPDATE: The exact code
First I have a global.js file which apply bsmSelect plugin to some select multiples (.quizzes):
$('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
And then, in the php file I define the updateQuizzes function and bind it to the select simple (project_id) change event:
<script type="text/javascript">
function updateQuizzes(project_id) {
var r = $.ajax({
type: 'GET',
url: '<?php echo url_for('event/updateQuizzes')?>'+'<?php echo ($form->getObject()->isNew()?'':'?id='.$form->getObject()->getId()).($form->getObject()->isNew()?'?project_id=':'&project_id=')?>'+project_id,
success: function() { $('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
}); }
}).responseText;
return r;
}
$('#project_id').change(function(){
$('.quizzes').html(updateQuizzes($(this).val()));
});
</script>
As I told, the AJAX request works without problems, but not the calling bsmSelect the second time...
Not sure if this is what the problem is, but you could try
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val())).trigger('change');
}
This triggers a change event on select_multiple, and might fire bsmSelect. I'm not sure what the problem here is exactly, but that's the best I can come up with.
I think you want to set your HTML in the success of the Ajax call, something like:
function loadNewOptions(val) {
$.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).bsmSelect();
}
});
}
And then calling like:
$('#my_select_simple').change() {
loadNewOptions($(this).val());
}
$(document).ready(function() {
$('#my_select_simple').change() {
$('#my_select_multiple').load("your Url", function(){
$('#my_select_multiple').bsmSelect();
});
}
});
something like this should work.
.load will put whatever your url returns into #my_select_multiple
the first parameter is the url to load, and the 2nd is a function to call when it is done. which is where you need to set up your fancy selector.
Ok, I opened a ticket and bsmSelect developer has answered me in minutes. Great!
To let bsmSelect know about its select changes, you have to trigger a change event on the select. There is no need to call bsmSelect again.
So it can be that way:
function loadNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).trigger('change');
}
}).responseText;
return r;
}
$('#my_select_simple').change(function() {
loadNewOptions($(this).val());
});

What is the easiest/best way to show that an HTML element is AJAX Loading?

Sometimes in my application there are many elements loading so I want to show the typical AJAX spinner above the control (or DOM node) with it disabled.
What is the easiest/best way to do that?
Ideally I would like to:
$("#myelement").loading();
$("#myelement").finishloading();
Or even better being able to do AJAX requests directly with the element:
$("#myelement").post(url, params, myfunction);
Being #myelement a regular node or form input.
You could use beforeSend and complete callbacks:
$.ajax({
url: 'script.cgi',
type: 'POST',
beforeSend: function() {
$('.spinner').show();
},
complete: function() {
// will trigger even if request fails
$('.spinner').hide();
},
success: function(result) {
// todo: do something with the result
}
});
Since you're already using jQuery, you may want to look into BlockUI in conjunction with Darin Dimitrov's answer. I haven't used it yet myself as I just came across this today, but it looks decent.
If you're writing a semi-large-ish application and anticipate making many AJAX calls from different places in your code, I would suggest that you either add a layer of abstraction over $.ajax, or create a helper function to avoid having boiler plate for your UI indicator all over the place. This will help you out a lot should you ever need to change your indicator.
Abstraction method
var ajax = function(options) {
$.ajax($.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
));
};
ajax({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
});
Helper method
var ajaxSettings = function(options) {
return $.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
);
};
$.ajax(ajaxSettings({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
}
}));
Also, I wouldn't suggest overwriting the $.ajax method itself.
what i've done in the past is, on post pass the element id (a containing div) to a function which replaces it's inner HTML with a loading image, and then in the post back replace it's content again with the updated real content.
If you want to show the spinner every when an ajax call is in progress I think you should use ajaxStart and ajaxStop.
$("#spinner")
.ajaxStart(function(){$(this).show();})
.ajaxStop(function(){$(this).hide();});

jQuery: Referencing the calling object(this) when the bind/click event is for a class

Thanks for reading this.
I am dynamically generating some data which includes a select drop-down with a text box next to it. If the user clicks the select, I am dynamically populating it (code below). I have a class on the select and I was hoping the following code would work. I tested it with an ID on the select and putting the ONE on the ID I got it to work. However, in changing the code to reference a class (since there will be multiple data groups that include a select with a text box next to it) and $(this), I could not get it to work. Any ideas would be helpful. Thanks
The relevance of the text box next to the select is the second part of the code...to update the text box when an option is selected in the select
.one is so the select is updated only once, then the .bind allows any options selected to be placed in the adjacent text box.
$('.classSelect').one("click",
function() {
$.ajax({
type: "post",
url: myURL ,
dataType: "text",
data: {
'_service' : myService,
'_program' : myProgram ,
'param' : myParams
},
success:
function(request) {
$(this).html(request); // populate select box
} // End success
}); // End ajax method
$(this).bind("click",
function() {
$(this).next().val($(this).val());
}); // End BIND
}); // End One
<select id="mySelect" class="classSelect"></select>
<input type="text">
$(this) is only relevant within the scope of the function. outside of the function though, it loses that reference:
$('.classSelect').one("click", function() {
$(this); // refers to $('.classSelect')
$.ajax({
// content
$(this); // does not refer to $('.classSelect')
});
});
a better way to handle this may be:
$('.classSelect').one("click", function() {
var e = $(this);
$.ajax({
...
success : function(request) {
e.html(request);
}
}); // end ajax
$(this).bind('click', function() {
// bind stuff
}); // end bind
}); // end one
by the way, are you familiar with the load() method? i find it easier for basic ajax (as it acts on the wrapped set, instead of it being a standalone function like $.ajax(). here's how i would rewrite this using load():
$('.classSelect').one('click', function() {
var options = {
type : 'post',
dataType : 'text',
data : {
'_service' : myService,
'_program' : myProgram ,
'param' : myParams
}
} // end options
// load() will automatically load your .classSelect with the results
$(this).load(myUrl, options);
$(this).click(function() {
// etc...
}); // end click
}); // end one
I believe that this is because the function attached to the success event doesn't know what 'this' is as it is run independently of the object you're calling it within. (I'm not explaining it very well, but I think it's to do with closures.)
I think if you added the following line before the $.ajax call:
var _this = this;
and then in the success function used that variable:
success:
function(request) {
_this.html(request); // populate select box
}
it may well work
That is matching one select. You need to match multiple elements so you want
$("select[class='classSelect']") ...
The success() function does not know about this, as any other event callback (they are run outside the object scope).
You need to close the variable in the scope of the success function, but what you really need is not "this", but $(this)
So:
var that = $(this);
... some code ...
success: function(request) {
that.html(request)
}
Thanks Owen. Although there may be a better to write the code (with chaining)....my problem with this code was $(this) was not available in the .ajax and .bind calls..so storing it in a var and using that var was the solution.
Thanks again.
$('.classSelect').one("click",
function() {
var e = $(this) ;
$.ajax({
type: "post",
url: myURL ,
dataType: "text",
data: {
'_service' : myService,
'_program' : myProgram ,
'param' : myParams
},
success:
function(request) {
$(e).html(request); // populate select box
} // End success
}); // End ajax method
$(e).one("click",
function() {
$(e).next().val($(e).val());
}); // End BIND
}); // End One

Categories