The data that is coming as part of ajax call from my business class is as follows:
[{
"user_action": "<button class='detail-icon' title='Vehicle Pass History'onclick='javascript:openPopUpWagonList('DIM 008065');'> <img src='/WIMS/images/icon_detail.png'></button>",
"VEHICLE_ID": "DIM 008065",
"setFlag": "<img src='/WIMS/images/wims-tick.gif'>",
"clrFlag": "<img src='/WIMS/images/wims-tick.gif'>",
"setDate": "31 Jul 2010 11:11",
"lastClearDate": "24 Aug 2010 07:26",
"noOfdays": "24",
"ownerCode": "",
"operatorCode": "",
"maintainerCode": "",
"severity10Pass": "~",
"plot": "<button class='detail-icon' title='Plot' alt='Detail'onclick='javascript:popUpStepChangeListGraph('DIM 008065');'> <img src='/WIMS/images/icon_detail.png'></button>",
"activeFlag": "1"
}, {
"user_action": "<button class='detail-icon' title='Vehicle Pass History'onclick='javascript:openPopUpWagonList('N 005276');'> <img src='/WIMS/images/icon_detail.png'></button>",
"VEHICLE_ID": "N 005276",
"setFlag": "<img src='/WIMS/images/wims-tick.gif'>",
"clrFlag": "",
"setDate": "31 Aug 2011 10:05",
"lastClearDate": "24 Mar 2011 10:45",
"noOfdays": "0",
"ownerCode": "",
"operatorCode": "",
"maintainerCode": "",
"severity10Pass": "~~~",
"plot": "<button class='detail-icon' title='Plot' alt='Detail'onclick='javascript:popUpStepChangeListGraph('N 005276');'> <img src='/WIMS/images/icon_detail.png'></button>",
"activeFlag": "1"
}]
Here I have taken only 2 records for convenient readability, but I am displaying more than 150 records of this kind.
Now my ajax call format from my jsp page is as follows:
$.ajax({
type: "POST",
url: f_reqAction, // url is set already
data : {maintainer:maintainerValue,show:showValue},
dataType:'json',
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:80000, /* Timeout in ms */
success: handleApplyEventResponse,
error: handleResponseError
});
function handleApplyEventResponse(response) {
// response is coming from my business class
$("#stepChangeData").jqGrid('clearGridData');
if(response.length > 0){
for(var i=0;i<response.length;i++){
jQuery("#stepChangeData").jqGrid('addRowData',i+1,response[i]);
}
$('#stepChangeData').setGridParam({rowNum:response.length});
}
}
When I want to remove the data by calling jQuery("#gridtabID").jqGrid('clearGridData'); a javascript error is coming prompting to stop running the script. but if the data size is small like 20 or 30 the problem does not come.
I understand populating response data by calling jqGrid('addRowData' inside for loop is not efficient when the data is this much large. but i could not find a jqgrid api which can add this response data directly in the grid without any looping.
And i could not create the buttons contained in my json data through formatter option of colModel as I found it extremely difficult to create that type of button by formatter.So I created it in my business ligic and sending it to jsp page with json data as part of the ajax respose.
So in the above context, I would have loved to have an api which could have set this json data into the grid at a shot (i.e without any looping). And I think this way this script problem could have been averted as well.
The best way to fill jqGrid with the JSON data from the server to use datatype: 'json' and load the data from the server. jqGrid is very flexible and one can load practically any data. One need just to use corresponding jsonReader or jsonmap property of colModel. Sometimes one need additionally use ajaxGridOptions option, serializeGridData or beforeProcessing callbacks. One should additionally use gridview: true option of jqGrid.
The difference to the usage of addRowData is huge. The main disadvantage of the usage of addRowData is that the data will be placed in the grid row per row. The problem is that if you modify an element on the page or insert a new one the position of all existing elements on the page have to be recalculated by the web browser. Because you use addRowData in the loop, then positing of the row which will be inserted first have to be recalculated also after any insertion of the next rows. So The more rows need be inserted the more slowly will be the code. Because of the problem jQuery 1.4 introduced the method jQuery.detach which allows to remove temporary an element from the page, modify it and then place it back with any standard jQuery methods like jQuery.after, jQuery.append and many other.
If you use datatype: 'json' and gridview: true the full body of grid will be constructed as string and then placed in the grid as one insert operation. So you will get much more better performance as with addRowData in case of many inserted rows.
UPDATED: On the demo I show how the loading of the data directly in jqGrid can be implemented. I recommend you to use predefined or custom jqGrid formatters. For example to be able correctly sort the data one have to include date in ISO 8601 format and use formatter: 'date' with the corresponding options to display the date.
Additionally I don't recommend you to use spaces inside of ID. I supposed that VEHICLE_ID is unique id of your data. I used it, but removed all spaces from the value.
About the usage function inside of postData I recommend you to read my old answer.
The most important part of the code of the demo you find below
var maintainerValue = 1, showValue = 200, $grid = $("#list");
$grid.jqGrid({
url: 'DebaprasadJana.json',
datatype: 'json',
mtype: "POST",
postData: {
maintainer: function () {
// if maintainerValue will be get from a field on the page
// one can get the data here directly like
// return $("#maintainer").val();
return maintainerValue;
},
show: function () {
return showValue;
}
},
loadonce: true,
gridview: true,
jsonReader: {
repeatitems: false,
id: function (obj) {
// we can use VEHICLE_ID as the rowid, but cut spaces
return obj.VEHICLE_ID.replace(/\s/g, '');
},
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
}
});
$("#reload").click(function () {
// next two lines simulate reading of the
// current values of maintainerValue and showValue
maintainerValue++;
showValue--;
// we need reset datatype only if we use loadonce:true
$grid.jqGrid('setGridParam', {datatype: 'json'})
.trigger('reloadGrid');
});
Related
I got a database with one table in it.
Table has Company and Time columns, and some more, but these two are important.
So the user makes an appointment through the filling of the form.
In the form I have 2 <select>s - Company And Time, so he chooses both from the selections.
He clicks a button and the form is stored in the database.
How do I use AJAX to retrieve all the hours(Time) that are in use, and then disable them accordingly.
For example: I made the appointment selected Nokia from Companies and 9:30 from Time dropdowns. Now You want to make the appointment with Nokia but the 9:30 time is disabled because it has already been used.
What would be the correct way to use AJAX for this:
this is my structure
function MakeApp() {
var AppWith = $("#CompanySelect").val();
var AppTime = $("#TimeSelect").val();
var Yritys = $("#YritysNtext").val();
var Henkilonimi = $("#HenkilonimiText").val();
var Asema = $("#AsemaText").val();
var PuhelinNR = $("#PuhelinText").val();
var EMail = $("#EMailText").val();
var Keskustelun = $("#KeskustelunText").val();
var app = { AppWithYritys: AppWith, AppTime: AppTime, YritysN: Yritys, Henkilonimi: Henkilonimi, Asema: Asema, PuhelinNR: PuhelinNR, EMail: EMail, Keskustelun: Keskustelun }
var request = $.ajax({
type: "POST",
data: JSON.stringify(app),
url: "/api/Appointments",
contentType: "application/json",
dataType: "html"
});
request.done(function (podaci) {
if (podaci != -1) {
alert("You Have successfully made an appointment");
location.assign("BookAppointment.html");
}
else {
$("#p1").html("Greska pri unosu");
}
});
request.fail(function (gr) {
$("#p1").html(gr.statusText);
});
};
Actually it's your server job to manage data and database. AJAX is only a way to send information to a server aysnchronously. What you could do, is when you load the page, you retrieve only the occupied time with AJAX, you disable their options in your select, and whenever your server receive an request, it checks if there is an available place for the company and times.
I'm sorry i don't have a code for your since I think it's pretty clear. If it's not, feel free to comment, i'll try to help you the best i can.
Edit
Here I have a few lines of code, it's not complete since we are missing a few informations but it is the main algorythm.
Your server:
{GET}
public void getUnavailable() {
//get all times from Databases for today's date.,
//Encode them in JSON.
//returns the times.
}
Lets assume that your JSON looks like this:
[
{
"company": "Nokia",
"times": [
"9:30",
"10:00",
"10:30"
]
}
]
You need to retrieve your JSON and parse it to disable the time in the selected select:
$(document).ready(function(){
$.ajax({
'url': API_URL + 'event/getUnavailable',
'method': 'GET',
'success': function(data) {
$.each(data.data, function($index, $company){
var select = /* .. Get the Select of the current company .. */
$.each($company.times, function($index, $times){
select./*.. Find the time associate with $time .. */.setDisable(true); // I don't know if setDisable is the correct function, you might want to check this out.
})
})
},
'error': function(error) {
console.error(error.data);
}
});
$('.myForm').submit(function(){
// This is where you submit your data to your server.
$.ajax({
'url': API_URL + "event/create",
'method': 'POST',
'data': /* your data */,
'success': function(){
console.log('success');
},
'error': function(error) {
console.error(error);
}
})
});
})
This is the most I can do with the info I have.
The real way to handle this, is whatever web technology you have behind /api/Appointments, is to return whatever appointments are available. Your variable names don't make much sense to me, so try to understand what the code below does.
$.get( "/api/Appointments", JSON.stringify(app) )
.done(function( data ) {
//note that the "data" variable holds your returned appointments
//I would return a json document of available appointment times to filter your select
//sample json would look something like this
// { "availableAppointments": ["9:30 AM", "10:00 AM"] }
// and then iterate through available appointments and populate your select
for(var i = 0; i < data.availableAppointments.length; i++){
$('#yourSelectId').append($('<option>', {
value: 930,
text: data.availableAppointments[i]
}));
}
});
Please note this code may not be syntactically correct.
Here are some links that helped me answer this for you, in case they might help.
Adding options to a <select> using jQuery?
https://api.jquery.com/jquery.get/
I want to bind repeater with entity framework, that call a procedure in database(Speed purposes), i create an ajax web method to be called from jquery code to sent parameters. so it will decide what data to display.
Below is the ajax call that will sent the parameter to showResult web method, i use the ajax code to handle all data within one page, because i have drop down lists to handle user selections(every selection reflect a query in database).
$.ajax({
url: "WebService.asmx/showResult",
type: "post",
data: JSON.stringify({
"dateFrom": $('#txtDateFrom').val(),
"dateTo": $('#txtDateTo').val(),
"ddlType": $("#ddlType").children("option").filter(":selected").val(),
"ddlTer": $("#ddlTer").children("option").filter(":selected").val()
}), // parameters
beforeSend: function () {
$('#loader').html('<img src="Images/loading.gif" />');
},
contentType: "application/json; charset=utf-8",
success: function (result) {
$('#loader').html('');
//To delete the whole tr except the first one.
$("#tblUsers").find("tr:gt(0)").remove();
$('#tblUsers').append(JSON.stringify(result));
},
error: function () {
alert('error');
}
});
also, below is the web method showResult code that will call the proc with parameters:
public string showResult(DateTime dateFrom, DateTime dateTo)
{
string result = " ";
var sp = db.select_alltypes(dateFrom, dateTo).ToList();
foreach (var u in sp)
{
result += "<tr>";
result += "<td>"+u.depno+"</td>";
result += "</tr>";
result += "</table>";
}
return result;
}
I used to return a table and to append it to the table in .aspx page but i stop, because I want to show 3 tables in the page every table data will present an execution of procedure so, I don't know how to handle this, instead of tables i use 3 repeaters.
so i want to a way to change the DataSource of the repeater immediately whenever the user press a button.
Note: If any one have an idea to present three tables instead of using
repeaters, please provide it here.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm working on a feature for a heatmap. When I click on a cell in the chart, a boxplot will pop up, and I am using django and highcharts models for the implementation.
Currently, I am stuck with the passing of variable from a javascript function to the python server side. I know for django there is a post and get method, but I don't have a form in this case, only the clicks. Whenever I click on a cell in the heatmap, I would like to pass the x-label and y-label strings to the python server, process and grab data in python, and then feed the data back to the pop-up boxplot. Thank you !
$(function () {
$('#container').highcharts({
chart: {
type: 'heatmap'
},
plotOptions: {
series: {
events:{
click: function cellClick() {
var $div = $('<div></div>')
.dialog({
title: this.name,
width: 400,
height: 300
});
window.chart = new Highcharts.Chart({
chart: {
renderTo: $div[0],
type: 'boxplot'
},
series: [{
name: 'Observations',
data: [
//here I would like to insert data passed from the python view
// on click of a cell in the heatmap
],
}, {
name: 'Outliers',
color: Highcharts.getOptions().colors[0],
type: 'scatter',
data: [//data from python view],
}]
})
}
}
}
},
xAxis: {
opposite: true,
categories: label,
labels:{
formatter: function(){
//I would like to pass factor_x to the server(python) on click
//of a cell in the heatmap
var factor_x = this.value;
if (factor_x.length > 6){
return factor_x.substr(0,6) ;
}else{
return factor_x;
}
}
},
},
yAxis: {
categories: label2,
labels:{
formatter: function(){
// pass factor_y to the server side on-click
var factor_y = this.value;
if (factor_y.length > 7){
return factor_y.substr(0,7) + "...";
}else{
return factor_y;
}
}
},
},
series: [{
name: 'Factor Correlation',
data: correlation,
}]
});
});
Okay so what you can do is write click functions for the cells of heatmaps.
In the onclick functions, you'll get the value of that cell by using the "this" variable in javascript, as it tells you what container or DOM element you clicked.
So now $(this).data or whatever attribute of that element has the required information (which you can check in your browser on your console by inspecting element) will give you the data you want to send to your views so that you can manipulate it.
So for that you'll call another function say send_data() from this onclick function and you'll pass this required information to that function maybe as one or two variables or as a list like this:
send_data(info);
where info is a list of all the required elements.
Now inside the send_data function you'll make an ajax call to the URL corresponding to the class or def in your views to which you want to supply this information like this:
function send_data(req_info) {
$.ajax({
type: "POST",
url: "/heatmap_cell_data/",
data: req_info,
// dataType: 'json',
success: function(response){
console.log(response);
}
});
}
Now in your urls.py you'll associate a def/class in views corresponding to the URL in your Ajax function. You'll receive this data in request.POST, then you'll do whatever you want to in that view and finally return an HTTPResponse(whatever data you want to) back to the javascript which you'll receive as response in your success function.
NOTE -> Sending an HTTPRespnse from views.py back to the Ajax request is a must or else you'll get an error that no HTTPResponse found.
Now you can use this response data to modify your heatmaps again.
I hope this was what you were looking for.
The most secure way to handle this with Django is to pass the CSRF token along with each AJAX request you post data within. The easiest way to do this is to put this on your page (it appears you are using jQuery so this should work as is):
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
What this does is grab the CSRF cookie that Django typically stores on the browser when someone accesses a form and send it along with the AJAX requests.
This means you will also need something like this on the page somewhere:
<form>
{% csrf_token %}
</form>
On your view function, you will want the csrf_protect decorator. You can also use require_post to only accept POST data on this view:
#require_post
#csrf_protect
def my_view(request):
pass
The most ideal way to handle the functionality you are looking for is when you need a plot, post it to a view like the above and then have another view for getting the latest results. This will also work better if multiple people can mess with it at the same time.
In jQuery that would mean using something like:
$.post('/my_view/', some_json_data);
And to collect the data you would use:
$.get('/my_view_updates/', success: somefunctiontoparseresponse);
I know this question has been asked before but I have some serious weird behaviour here...
I have a DIV containing a list of anchors which are pulled via ajax from a php file (mysqli). I can dynamically add, edit and delete the items (categories) on this list. This works fine. It looks like this:
However, after a category is created I want to automatically select it. Same goes for edited categories.
And, after the page first loads, the category "Alle" should be selected by default.
I have an external categories-management.js file which contains these functions amongst other things:
function selectRootCategory () {
selectedcategoryname = "Alle";
categegorySelected = 0;
$("#training_management_categories_items>ul>li>a").removeClass('categories_selected');
$('#training_management_categories_list_a_all').addClass('categories_selected');
}
function selectEditedCategory() {
categorySelected = 1;
categoryid = 'training_management_categories_list_a_' + selectedcategoryid.toString();
$("#training_management_categories_items>ul>li>a").removeClass('categories_selected');
$('#'+categoryid).addClass('categories_selected');
}
On the main page I call this function:
$(document).ready(function() {
GetCategories();
CheckIfCategoryChecked();
selectRootCategory();
});
So basically, what should happen when the page first loads, the category "Alle" should be selected. This doesn't work though.
I would think I got the function wrong, BUT if I delete an Item, the selectRootCategory()-function is called, too and then it works. This is the function in which it works (housing in categories-management.js, too):
function submitDeleteCategory() {
var url = './ajax/training_management_data.php';
$('#delete_category_dialog_error').hide();
$.ajax({
url: url,
type: "POST",
data: {
action: 'delete_category',
category_id: selectedcategoryid,
},
dataType: 'JSON',
success: function (data) {
if (data == 'success') {
GetCategories();
CheckIfCategoryChecked();
selectRootCategory(); //THIS WORKS
categorySelected = 0;
$('#delete_category_dialog').dialog('close');
}
else {
$('#delete_category_dialog_error').html('<b>Fehler:</b><br>Fehler beim Löschen der Kategorie.')
$('#delete_category_dialog_error').show( "blind" ,300);
}
}
});
}
However, the selectEditedCategory()-function never works (which is called after you edited or created a category so it gets selected) though the given variable (categoryid) is correct, tested with alert. The function that calls selectEditedCategory is also placed in categories-management.js.
So my questions are:
Why does selectRootCategory() work when it is called via success-function in the delete-dialog but not when called via $document.ready()?
Why doesn't selectEditedCategory() work at all?
BTW don't get fooled by the categegorySelected variable, this is meant to determine if the edit- and delete-button are enabled or not. "Alle" is a fake category which contains all items from all categories and cannot be deleted or edited ("Alle" means "all" in German).
I'm using jquery-1.10.2.
Edit: To make things more clear: The ids on the items are correctly set when I call GetCategories();. This function does the following:
function GetCategories()
{
var url = './ajax/training_management_data.php';
$('#training_management_categories_items').html('<ul style="list-style: none; margin-left:0px; margin-top:0px; padding:0px;" id="training_management_categories_items_ul"></ul>');
$('#training_management_categories_items_ul').append(' \
<li class="training_management_categories_list"> \
Alle \
</li> \
');
$.ajax({
url: url,
type: "POST",
data: {
action: 'get_categories',
},
dataType: 'JSON',
success: function (data) {
$.each(data, function(index, data) {
$('#training_management_categories_items_ul').append(' \
<li class="training_management_categories_list"> \
'+data.name+' \
</li> \
');
});
}
});
}
It works fine which is proven by the fact that I can delete and edit the categories (the functions to do so require the id of the element. However I read the ID not via the ID field as this contains a string but by the attribute "data-id" which only contains the ID (as you see in above code). So the problem lies solely at the jQuery part and not at the ajax-part.
Edit2: When I add selectRootCategory() to the success-function of GetCategories(), it works on page load. But I still don't get why it doesn't work with document.ready(). I cannot use it in GetCategories(), though because it would de-select any item and select "Alle" instead.
I can still not get selectedEditedCategory to work.
The var categoryid contains a valid ID though, e.g. training_management_categories_list_a_70.
You have to parse the data coming back from the server and add a class to it.
like
$.ajax({
...
success:function(data){
$.each(data,function(singleData){
$(singleData).addClass('blahblah');
});
}
...
});
Hope this helps
I have built my JQGrid table with dynamic column in this way (ajax call) :
$.ajax(
{
type: "POST",
url: "Scripts/GetSummaryInformation.php",
data: { domain: "<?php echo $domain; ?>", etc. },
dataType: "json",
success: function(result)
{
var colD = result.gridModel;
var colN = result.colNames;
var colM = result.colModel;
var colSpan = result.colSpan;
jQuery("#FinalRatingList<?php echo $domain; ?><?php echo $companyID; ?>").jqGrid({
jsonReader : { repeatitems: false, root:"dataset", cell: "cell", id: "0" },
url: 'Scripts/GetSummaryInformation.php',
datatype: 'json',
mtype: 'POST',
postData : { domain: "<?php echo $domain; ?>", etc.},
datastr : colD,
colNames:colN,
colModel :colM,
height: 'auto',
pager: jQuery('#FinalRatingListPager'),
caption:"Final Rating",
loadComplete: function(data){
console.info("FinalRatingList Success");
notyMsg ("loadComplete", "info");
},
...
and it works fine :)
When I create a column in the PHP file like using the cellattr
$response->colModel[$colMod++] = array ('name'=>'DIR'.$projectName, 'index'=>'DIR'.$projectName, 'width'=>'40', "cellattr"=>"rowSetting" );
there is absolutely no effect at all.
Even when I put code directly in the cellattr like this
"cellattr"=>"function( rowId, value, rowObject, colModel, arrData) { return ' style=\"background:orange\"'}" );
Does anyone have faced or know the solution to this problem?
Thanks in advance for your collaboration
UPDATE
Thanks Oleg. It worked greatly for cellattr and for template (which is a really good advice).
For those who are interested here is the code:
var rowSetting = function (rowId, val, rawObject, cm) {
return 'style="background-color: orange;';
};
var cellattrMapping = {
"rowTemplate": rowTemplate
};
var rowTemplate = {
width:120,
cellattr: rowSetting
};
AJAX CALL
success: function(result)
{
...
for (i=0; i<colM.length; i++) {
cm = colM[i];
if (cm.hasOwnProperty("template") && cellattrMapping.hasOwnProperty(cm.template))
{
cm.template = cellattrMapping[cm.template];
}
It seems that what you do looks like you set cellattr to string value cellattr: "rowSetting" instead of initialysing it to the pointer of function. The problem is there are some restrictions in the data which you can send as JSON. It supports strings, numbers, boolean, arrays and objects, but you can's send functions as part of JSON data.
One can suggest many workarounds for the problem. For example you can create JavaScript code with some cellattr functions which you use. You can place all the cellattr functions which you need in one object: your custom cellattr "string to functions mapping". Inside of success callback you can examine result.colModel items for cellattr property. If you found cellattr property you should just replace the string value to the corresponding function reference.
In the old answer I described more detailed very close solution. You can use the same approach for cellattr.
More better way in my opinion would be to use template attribute of colModel more active (see the old answer). You will have the same problem as before, but you could provide common templates which you use in different grids and post first string values as the value of template attribute of colModel. Then you could replace the value to JavaScript object which hold all required implementation details. The main advantage of usage column templates is sharing common code over multiple grids. The information in colModel become smaller and more readable. The templates could be easy modified.