I have several toggles on my page, all using class psettings which allows the triggering of a single script which performs an AJAX call to update flags in a MySQL database table. This works fine if I click slowly. I can click all the buttons at normal speed and the database updates as expected but unchecking, sometimes does not clear the flags in the DB. If I go slow, pause in between click, it works OK. I cannot prevent how fast a user will click the toggles but need a way to make sure the updates are consistent, maybe a delay or a flush, etc.
<script type="text/javascript">
$('.psettings').change(function(){
//event.preventDefault();
var token = $("input[name=<?php echo csrf_token(); ?>").val();
var ename = this.name;
var evalue = ' ';
if($("input[type='checkbox']").is(":checked"))
{
var evalue = 'X';
}
$.ajax({
type: 'post',
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '<?php echo base_url('setprivacy');?>',
data: {'<?php echo csrf_token(); ?>' : token, 'element_name' : ename, 'checked' : evalue },
dataType: 'json',
success:function(data){
$('input[name="fmpfy_tk"]').val(data.csrf);
},
error:function(data)
{
$('input[name="fmpfy_tk"]').val(data.csrf);
alert('Error occurred ' data.col_name);
}
});
});
</script>
<?php
echo form_open();
?>
<div >
<div >
<h2 ><i ></i>Privacy Settings</h2>
<div >
<div >
<div >
<input type="checkbox" role="switch" name="flag_display_fullname" value="">
<label for="flag_display_fullname">Display full name in profile and posts</label>
<i rel="tooltip" title="<?php echo lang('Tooltips.display_fullname'); ?>"></i>
</div>
<div >
<input type="checkbox" role="switch" name="flag_display_smaccounts" value="">
<label for="flag_display_smaccounts">Display social media accounts on posts</label>
<i rel="tooltip" title="<?php echo lang('Tooltips.display_sm_accounts'); ?>"></i>
</div>
<div >
<input type="checkbox" role="switch" name="flag_receive_fy_emails" value="">
<label for="flag_receive_fy_emails">Receive periodic emails from FY.</label>
<i rel="tooltip" title="<?php echo lang('Tooltips.receive_fy_emails'); ?>"></i>
</div>
</div>
</div>
</div>
</div>
<?php
echo form_close();
?>
public function maintain_privacy_settings()
{
helper(['form','url']);
if ($this->request->isAJAX())
{
$UserModel = new \App\Models\User_model();
//Determine update column name
$element_name = $this->request->getPost('element_name');
$col_name;
switch ($element_name)
{
case 'flag_display_fullname':
$col_name = 'show_fullname';
break;
case 'flag_display_smaccounts':
$col_name = 'display_sm_accounts';
break;
case 'flag_receive_fy_emails':
$col_name = 'fy_notification_emails';
break;
}
if($UserModel->set_privacy_flag($this->data['userid'],$col_name,$this->request->getPost('checked')))
{
return json_encode(['success'=> 'success', 'csrf' => csrf_hash()]);
}
else
{
return json_encode(['error' => 'error', 'csrf' => csrf_hash(), 'col_name' => $this->request->getPost('element_name') ]);
}
}
}
CodePudding user response:
Your problem happens when multiple requests will be sent to server but their responses won't come back in order. So this what stores on server will not be same as one on the UI.
To Solve this issue you can use many techniques but simplest on is that to block that specific UI element till the response received from server. For this purpose you can disable element before ajax call and then enable it on success or fail functions.
You can also assign a sequence number to each request and apply the highest one and ignore the rest.
Also you can implement a queue for your requests and handle them that way in order.
Edit:
Also there is a problem with your jquery code. You're not getting checked state of specific input. Try something like below:
if($(`input[name='${ename}']`).is(":checked"))
{
var evalue = 'X';
}