I've got a piece of code that populates a dropdown based on the selection of another dropdown. This propogates through 4 dropdowns so:
selection -> selection based on 1 -> selection based on 1 & 2 -> selection based on 1, 2, & 3.
My issue is that sometimes the selection only comes up as 1 item, making it such that the user cannot "fire" the onchanged event. As such, upon population, I want to set the selected index to 0. Easy peasy, right?
So here's my code (edited to include full javascript function):
function FillProject() {
var BusinessAreaDropDown = document.getElementById("BusinessAreaDropDown");
var BusinessAreaSelection = BusinessAreaDropDown.options[BusinessAreaDropDown.selectedIndex].text
var GenericProjectDropDown = document.getElementById("GenericProjectDropDown");
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
}
var GenericProjectSelection = GenericProjectDropDown.options[GenericProjectDropDown.selectedIndex].text
#* Get list from C# for GenericProjects matching *#
$.ajax({
url: '/Home/FillProject',
type: "GET",
dataType: "JSON",
data: { BusinessArea: BusinessAreaSelection, GenericProject: GenericProjectSelection },
error: function (error) {
alert(error);
},
success: function (Projects) {
$("#ProjectDropDown").html("");
$.each(Projects, function (i, project) {
$("#ProjectDropDown").append(
$('<option></option>').val(project).html(project));
});
}
})
}
This generates an error. If I place an alert after the if statement, it says that the selected index is still -1. Here's where stuff gets weird. If I place an alert INSIDE the if statement it pops up saying that the selected index is -1 before changing, 0 after changing, and actually changes the selectedIndex to 0, causing the code to work. If I remove the alert statement, it goes back to failing. What's happening here?
Examples:
Works->
if (GenericProjectDropDown.selectedIndex == -1) {
alert(GenericProjectDropDown.selectedIndex);
GenericProjectDropDown.selectedIndex = 0;
}
Works->
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
alert(GenericProjectDropDown.selectedIndex);
}
Fails ->
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
}
Solution! Thanks to #charlietfl
I had some ajax that was running in a previous code chunk populating the dropdown and it wasn't finixshed before running the second script because it was asynchronous. By adding:
$.ajax({
url: '/Home/FillProject',
type: "GET",
dataType: "JSON",
async: false, //this line
data: { BusinessArea: BusinessAreaSelection, GenericProject: GenericProjectSelection },
error: function (error) {
alert(error);
},
success: function (Projects) {
$("#ProjectDropDown").html("");
$.each(Projects, function (i, project) {
$("#ProjectDropDown").append(
$('<option></option>').val(project).html(project));
});
The issue was resolved!
Related
I have UI with a list of users in a table. Each entry / user has two buttons. One of the buttons is a 'check' button.
<button type="submit" id="$id_from_db" class="bg-aqua btnCheckUser">Check</button>
When a check button is clicked for a particular user a POST request is sent to a server. While the request is loading all buttons should be disabled, the button which started the request should change its class from bg-puple to bg-aqua
and its text from Check to Checking.... If the request returns an error (which is indicated by result having the value 1) the button should change its class from bg-aqua to bg-danger. If there is no error the class should change from bg-aqua to bg-navy and the text from Checking... to User Okay.
I'm able to achieve this but it does not only affect the button which started the request but all buttons.
This is my code:
$(document).on("click", ".btnCheckUser", function() {
var Item_Number = $(this).attr("Item_Number");
/************************** MANIPULATE BUTTONS *******************************************************************************/
$(this).removeClass('bg-purple').addClass('bg-aqua');
$(this).html('Checking ...');
$(this).attr("disabled", true);
$('.btnViewUser').attr("disabled", true);
/******************************* PROCESS AJAX **************************************************************************/
var value = {
Item_Number: Item_Number
};
$.ajax({
url: "./plugins/serverside/CheckUserStatus",
type: "POST",
data: value,
success: function(data, textStatus, jqXHR) {
var data = jQuery.parseJSON(data);
if (data.result == 1) {
$(this).removeClass('bg-aqua').addClass('bg-danger');
$("#CheckUser").html('Failed!');
$('.btnCheckUser').attr("disabled", false);
$('.btnViewUser').attr("disabled", false);
setTimeout(function() {
var table = $('#User_Table').DataTable();
table.ajax.reload(null, false);
}, 3500);
} else if (data.result == 2) {
//------------------------ IF User Okay -------------------------------------------------------------------------------------------------------------------
$("#CheckUser").removeClass('bg-aqua').addClass('bg-navy');
$("#CheckUser").html('User Okay');
$('.btnCheckUser').attr("disabled", false);
$('.btnViewUser').attr("disabled", false);
}
How can I fix this and only affect the button which started the request, but still disable all buttons when a request is loading?
JSFiddle
I stripped the code down to the parts which matter for the button logic. I'm using a dummy API and I randomly generate the result value as I have no access to the actual API you're using.
$(() => $('.btnCheckUser').on('click', ({ target }) => clickHandler(target)));
function clickHandler(button) {
// Disable all buttons when one of them is clicked
$('.btnCheckUser').prop('disabled', true);
$('.btnViewUser').prop('disabled', true);
// Remove all non standard classes, then add 'loading' class and text
$(button).removeClass('bg-purple').removeClass('bg-navy').removeClass('bg-danger').addClass('bg-aqua');
$(button).text('Loading...')
$.ajax({
url: 'https://reqres.in/api/users?delay=3',
success: raw => {
// Random result value
const result = Math.random() > 0.5 ? 1 : 2;
if (result === 1) {
// Something went wrong, add 'danger' class and text
$(button).addClass('bg-danger');
$(button).text('Failed!')
} else if (result === 2) {
// Everything went fine, add 'success' class and text
$(button).addClass('bg-navy');
$(button).text('Success!');
}
},
error: () => {
// Add 'danger' class if something goes wrong
$(button).addClass('btn-danger');
},
complete: () => {
// Enable all buttons as we got a response
$('.btnCheckUser').prop('disabled', false);
$('.btnViewUser').prop('disabled', false);
// Remove 'loading' class as we got a response
$(button).removeClass('bg-aqua');
}
});
}
This should give you the expected behavior.
hello there this is truly easy what you have to do is
function TheClickerFunction(){
$("body").on("click",".YourButton",function(){
//this will only affect the clicked element
$(this).attr("disabled",true);
});
}
$(document).ready(function(){
TheClickerFunction();
});
/*
i think creating a global counter and increment it on each element would b better*/
var GlobalCounter= 0;
function DynamicBuilder(){
var stringBuilder="";
for(var i = 0; i< lengthOfYourElement ; i++){
GlobalCounter+=1;
stringBuilder+="<input type='submit' id='myButton"+GlobalCounter+"'></input>";
}
$("body").append(stringBuidler);
}
in this way each time a click is made
$(".yourClass").click(function(){
var elementID = $(this).attr("id");
//here you can do what ever you want with its id
})
*/
$("#destination1" + countVar).autocomplete({
minLength : 3,
source : function(request, response) {
var url = configOptions.icaocodeUrl;
var term = request.term;
url=url+term;
console.log(url);
$.ajax({
url : url,
type : "GET",
data : request,
dataType : "json",
success : function(data) {
response(data.slice(0, 10));
//alert(data);
},error: function(xhr, textStatus) {
alert('error');
}
});
},
change:function(event,ui){
console.log("fired in dest2");
},close:function(event,ui){
console.log("close in dest2"+'#dof1'+countVar);
console.log(countVar);
$(this).parents('form').find('#dof1'+countVar)
.filter(function () { return $(this).val() === ''; })
.first().focus();
}
});
above is my code for autocomplete and autotab(autofocus) to next field for dynamically created elements.autotab(autofocus ) is working fine for normal html but it is not working for dynamically created elements only.
Are you trying to focus() on a tab that is being dynamically added? If so, you might be triggering focus() to soon and the DOM element might not be there.
Try wrapping the focus function into a setTimeout() function to test it out.
setTimeout(function () {
$(this).parents('form').find('#dof1'+countVar)
.filter(function () { return $(this).val() === ''; })
.first().focus();
}, 2000); // 2 seconds
Guys I have a javascript which has a each loop in which I am calling a particular function for each index value. This script executes on mouse scroll event upon reaching page end (lazy loading).
This is the main section of the script :
function (data) {
$.each(data, function (index, value) {
BindNotice(value);
});
}
Now the problem is, after the index reaches it max value, it restarts from the 0 index. So I am getting repeated data in my view. I want to restrict this script to only execute until the index has reached the max value. How would I go about doing this ?
EDIT : ADDED COMPLETE FUNCTION
function callMoreData()
{
$.ajax(
{
type: "GET",
url: "/api/values/getnotice",
dataType: "json",
crossDomain: true,
async: true,
cache: false,
allow: true,
success: function (data) {
$.each(data, function (index, value) {
BindNotice(value);
});
},
error: function (x, e) {
alert('problem while fetching records!');
}
} );}
From JS file :
$(".mainwrap .innnerwrap").mCustomScrollbar({
autoDraggerLength:true,
autoHideScrollbar:true,
scrollInertia:100,
advanced:{
updateOnBrowserResize: true,
updateOnContentResize: true,
autoScrollOnFocus: false
},
callbacks:{
whileScrolling:function(){WhileScrolling();},
onTotalScroll: function () {
callMoreData();
}
}
});
You could call another function, and then set it to do nothing after first go through.
function (data) {
updateData(data);
}
function updateData(data) {
updateData = function(data) {};
$.each(data, function (index, value) {
BindNotice(value);
});
}
Demo using alerts.
I made some edits to the code because it sounds more like you're getting multiple events and they are writing over previous events. After the first call, the function is basically set to do nothing. Thus the first callback will be the only callback that calls BindNotice.
Edit
As I mentioned in the comments, to ever receive data again through this channel, you need to restore updateData. Here's an example:
function restoreUpdateData() {
updateData = function(data) {
updateData = function(data) {};
$.each(data, function (index, value) {
BindNotice(value);
});
};
}
Use a global variable to block other requests to this function.
Something like:
var allow = true;
function (data) {
if(allow == true){
allow = false;
$.each(data, function (index, value) {
BindNotice(value);
});
allow = true;
}
}
I'm running into a strange issue, and it's happening across a few sites I maintain that use datatables.
Whenever I utilize fnPageChange, it does not work unless there is a setTimeout around it like this;
setTimeout(function() { oTable.fnPageChange(whatPage); }, 100);
or with an alert before it
alert('starting'); oTable.fnPageChange('last');
I understand this may be a sequence error of some sort, but I'm just unsure why the same issue would arise across multiple projects.
Here is the delete function I'm working with now:
function fnDelete(elem){
if (selected.length>0) {
var c;
c = confirm('Are you sure you want to delete the selected ${displayTableName}?');
if (c) {
// Create delete url from editor url...
var deleteURL = (urlstr.substring(0, urlstr.lastIndexOf('/') + 1)) + "delete.do";
deleteRecord(deleteURL,selected[0]);
if ( $('tableViewer tr').length === 0) {
// Reload the Table
oTable.fnPageChange('last');
//Send them back to the last page
}
}
}
}
Does anyone know what kind of issue this might be?
Here is deleteRecord:
function deleteRecord(deleteURL, iid){
var didDelete = false;
jQuery.ajax({
type: "POST",
url: deleteURL,
dataType:"html",
data:"recordID="+iid,
success:function(response){
didDelete = true;
oTable.fnDraw(true);
selected = [];
selectedRecord = [];
enableButtons(selected);
},
error:function (xhr, ajaxOptions, thrownError){
if ((xhr.status >=400) && (xhr.status < 500))
alert(xhr.responseText);
else
alert('error');
}
});
return didDelete;
}
You can try as below to
oTable.page(CurrentPageNo).draw(false);
Here, oTable is object of Datatable.
I have an application running with jquery-1.5.2.min.js. It works fine in IE9, 8, 7, FF and Chrome.
But there's this problem. I have a JavaScript function in a custom .js file using jQuery that rules the behaviour of a hidden field. Whenever a button is clicked, the hidden field is turned into a jQuery Autocomplete control, and loads the Autocomplete information through an Ajax call. The function is like this:
$.ajax({
type: "POST",
url: action,
dataType: "json",
data: "{type: '" + control + "', param:" + params + "}",
contentType: "application/json; charset=utf-8",
success: function (data) {
var dataTable = data;
$(selector).autocomplete({
minLength: 2,
source: dataTable,
open: function (e, ui) {
var options = $(this).data('autocomplete');
options.menu.element.find('a').each(function () {
var this_ = $(this);
var regex = new RegExp(options.term, "gi");
this_.html(this_.text().replace(regex, function (matched) {
return autocompleteTemplate.replace('%s', matched);
}));
});
},
focus: function (event, ui) {
$(selector).val(ui.item.label);
return false;
},
change: function (event, ui) {
if (!ui.item) {
var options = $(this).data('autocomplete');
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
valid = false;
options.menu.element.find('a').each(function () {
if ($(this).text().match(matcher)) {
valid = true;
return false;
}
});
if (!valid) {
if (control == "ProjectType") {
$('#selector').val("...");
$('#selector').attr('disabled', 'disabled');
$('#another.selector').val("");
}
// Remueve los valores inválidos.
$(this).val("");
$(selector).val("");
$(selector).data("autocomplete").term = "";
return false;
}
}
if (control == "ProjectType") {
$('#selector').val("");
}
},
select: function (event, ui) {
$(selector).val(ui.item.label);
$(hidden).val(ui.item.value);
if (control == "ProjectType") {
Autocomplete("ProjectSubType", action, ui.item.value);
// This is a function that changes the CSS for another HTML control
ProjectSubType(false);
}
return false;
}
});
}
});
So, whenever I change the browser type from IE8 to IE7 or IE9, or from IE7 to IE8 or IE9, after activating this field, the following exception is thrown from jquery-1.5.2.min.js
Runtime error from Microsoft JScript: Cannot get value of property
'type': the object is null or undefined
FYI:
The AJAX calls work. The autocomplete works properly and fires the events it has to fire when completed, in the order they have to be fired.
There is another control that fires another AJAX event (filling a jqGrid) which produces no mistake.
The conditional clause that you see in the code, "if (control == "ProjectType")", is meant to allow another control to turn into an Autocomplete if this control being used has an Autocomplete option filled in. Otherwise, it is disabled, as you can see (I changed its name to '#selector'). This also works properly: if you fill in a value in that Autocomplete, the other control is filled with the options needed.
Thanks
UDP
The function that calls the AJAX function is the following:
function SetSearchMenu(url, local) {
$('#advancedSearch').hide();
$('#advSearch').click(function () {
if ($('#advancedSearch').css("display") == "none") {
$('#advancedSearch').show();
$('#generalSearch').val("...");
$('#generalSearch').attr('disabled', 'disabled');
ProjectSubType(true);
}
else {
$('#dAdvancedSearch').hide();
$('#General').val("");
$('#General').removeAttr('disabled');
}
if (alreadyOpen == false) {
Autocomplete("SelectorOne", url, null);
Autocomplete("ProjectType", url, null);
Autocomplete("Selector", url, local);
alreadyOpen = true;
}
});
}
The parameters url and local are sent from the $(document).ready() function, and are filled with an #Url.Action() in string format and another variable hardcoded to one.