I am making an API service to send data to my API endpoint but I'm having a bit of trouble with it.
function getStockLevel(articleCodes) {
var ajaxCallData = [], stockLevels = [];
articleCodes.forEach(function(articleCode) {
if (isLocalStorageSupported() === true) {
if (localStorage.getItem(articleCode) === null) {
ajaxCallData.push(articleCode);
} else {
var localData = JSON.parse(localStorage.getItem(articleCode));
if ((Date.now() / 1000) >= localData['timestamp']) {
ajaxCallData.push(articleCode);
} else {
stockLevels[articleCode] = localData['stock'];
}
}
} else {
ajaxCallData.push(articleCode);
}
});
if (typeof ajaxCallData !== 'undefined' && ajaxCallData.length > 0) {
var article_codes = JSON.stringify(ajaxCallData);
$.ajax({
url : url,
dataType : 'json',
type : 'POST',
contentType : 'application/json',
data : {
article_codes : article_codes
},
success : function(result) {
console.log(result);
for (var code in result) {
if (result.hasOwnProperty(code)) {
var stockLevel = result[code];
stockLevels[code] = stockLevel;
if (isLocalStorageSupported() === true) {
var localStorageData = [];
localStorageData['stock'] = stockLevel;
localStorageData['timestamp'] = (Date.now() / 1000) + 120;
localStorage.setItem(code, JSON.stringify(localStorageData))
}
}
}
}
});
}
}
var codes = [40200, 40201];
var result = getStockLevel(codes);
I am using Ajax and jQuery to send an array of integers to my endpoint but if I check the data that's coming into my endpoint it returns: article_codes=%5B40200%2C40201%5D instead of the json I am expecting.
If I pass the ajaxCallData directly to the data property of the ajax call I get the same result except both values have the same key like so:
article_codes=40200&article_codes=40201
Any help would be appreciated.
data : ajaxCallData
Try Passing it in like this.
ajaxCallData already was an object with the articles_codes set as a key.
You don't need to JSON.stringify it at all.
I found the solution.
Balthasar was pretty close actually.
I needed to set the data like so data : article_codes
I now get the proper data in my endpoint controller.
Thanks for the help everyone!
Related
Here my return json from my Ajax method :
{"id_ac":"32","mail_uniq_ac":"mail#gmail.com","id_civ":"2"}
I would like to access to id_ac key value in my javascript but actually, I cannot.
this is my ajax controller :
public function executeAjaxGetActeur(sfWebRequest $request){
$id_ac = $request->getParameter('id_ac');
$acteur = Doctrine_Core::getTable('Acteur')->findOneByIdAc($id_ac);
return $this->renderText(json_encode($acteur->toArray()));
}
Here is my javascript where I need to get the key values
function showModalTempsPartenaire($id_ac){
var $id_ac = $id_ac;
$.post($url + "/ajax/get_acteur", {
id_ac: $id_ac
}, function (data) {
if (data && trim(data) != '')
console.log(data);
console.log(data['id_ac'])
});
}
The :
console.log(data);
Output me :
{"id_ac":"32","mail_uniq_ac":"mail#gmail.com","id_civ":"2"}
but console.log(data['id_ac']); return undifined
You're encoding the data to JSON in the server side using json_encode(), you need to decode it in the client side using JSON.parse() so you will be able to get the information from it like :
function showModalTempsPartenaire($id_ac){
var $id_ac = $id_ac;
$.post($url + "/ajax/get_acteur", {
id_ac: $id_ac
}, function (data) {
if (data && trim(data) != '')
data = JSON.parse(data);
console.log(data['id_ac'])
});
}
Working sample
var data = '{"id_ac":"32","mail_uniq_ac":"mail#gmail.com","id_civ":"2"}';
var obj = JSON.parse(data);
console.log(obj['id_ac']);
I'm correcting working on lazy loading for 200 array of objects and APIs are provided to me to extract JSON from the server (by passing index, row count as parameter for the get AJAX and on response I get the data and the Boolean of whether there are more rows or not). But the problem is that initially I was able to get the data of 10 from the 200 but while I set the scroll function on the div it displays duplicate data which are already appended on the div. Stucked in this problem for a day.
Hope you guys shed some light on me.
var listgen = (function() {
var mc = {};
mc.startindex = 1;
mc.rowcount = 10;
mc.hasmorerows = false;
mc.entity = "requests"
//Declared variables:
mc.initComponent = function() {
var entity = "requests";
mc.callAjaxForList(mc.entity, mc.startindex, mc.rowcount);
$("#reqbody").on('scroll', function() {
if (mc.hasmorerows && ($(this)[0].scrollHeight <= $(this).scrollTop() + $(this).innerHeight())) {
console.log('reached')
mc.callAjaxForList(mc.entity, mc.startindex, mc.rowcount);
}
console.log("scroll");
})
}
mc.callAjaxForList = function(entity, startindex, rowcount) {
var options = {
"list_info": {
"row_count": rowcount,
"start_index": startindex
}
}
$("#reqbody").addClass("loading");
$.ajax({
url: "/data/" + entity,
data: {
"input_data": JSON.stringify(options)
},
contentType: "application/json; charset=utf8",
type: "GET",
success: function(json) {
mc.hasmorerows = json.list_info.has_more_rows
mc.onDataLoading(json);
},
});
}
mc.onDataLoading = function(json) {
//this is where i append the data from the json
mc.startindex += mc.rowcount
}
return mc;
})()
listgen.initComponent();
Scroll is a very high-frequent event, so I think that you have several ajax calls with same data before actually your onDataLoading called, and range incremented. So I whould add mutex.
// ...
mc.loaging = false; // mutex
$("#reqbody").on('scroll', function(){
if(mc.hasmorerows && ($(this)[0].scrollHeight<=$(this).scrollTop()+$(this).innerHeight())){
console.log('reached')
if (!mc.loading) // add check here
mc.callAjaxForList(mc.entity,mc.startindex,mc.rowcount);
}
console.log("scroll");
})
}
mc.callAjaxForList= function(entity,startindex,rowcount){
// ...
mc.loading = true;
$.ajax({
// ...
success:function(json){
mc.hasmorerows=json.list_info.has_more_rows
mc.onDataLoading(json) ;
mc.loading = false;
},
error: ()=> mc.loading = false
});
}
So our mc.loading will tell us if ajax already completed (do not forget to reset it's value on ajax error)
I have two JS files as shown below (page1.js) and (page2.js for reference included below). I am basically referring to the following JSON response while working :
{
"webservice_status": {
"status": "SUCCESS",
"message": ""
},
"my_document_list": [{
"doc1": "445",
"doc2": "445",
"doc3": "445",
"doc4": "445",
"content": "Some text here to display"
}
]
}
Here is my page1.js related work:
$("#mydoclist").on('rowclick', function (event) {
row = event.args.rowindex;
datarow = $("#mydoclist").jqxGrid('getrowdata', row);
var response = JSON.stringify(datarow, null, 10);
var docID = datarow["doc_id"];
self.getMyDocumentContents(docID);
});
this.getMyDocumentContents = function (contentID_) {
var data = {
doc_id: contentID_
}
app_.get(data, self.processContent, app_.processError, url_name);
}// End of getMyDocumentContents
this.processContent = function(data_,textStatus_,jqXHR_) {
data_ = app_.convertResponse(data_,jqXHR_);
console.log("Checking for actual data_ content:", data_);
console.log("Actual Data Length Check for data_ content:", data_.my_document_list.length);
// debugger;
var collection = data_.my_document_list.length[0].content;
console.log("Collection Check",collection);
//debugger;
var source = {
localdata: collection,
datafields: [{
name: 'content',
type: 'string'
}],
datatype: "array"
};
var dataAdapter = new $.jqx.dataAdapter(source, {
loadComplete: function (records) {
debugger;
var html;
//Get data
var records = dataAdapter.records;
console.log("Check for records:",records.length);
var length = records.length;
html = "<div style='margin: 10px;'><pre>" + records[0].content + "</pre></div>";
$("#docContentPanel").jqxPanel('clearcontent');
$("#docContentPanel").jqxPanel('append',html);
},
loadError: function (xhr, status, error) { },
beforeLoadComplete: function (records) {
}
});
// perform data binding
dataAdapter.dataBind();
var panel = $("#docContentPanel");
var content = panel.html();
panel.jqxPanel({ width: '750', height: '500', scrollBarSize: 20 });
}// End of processContent
Here is my page2.js related work:
this.get = function (data_, done_, fail_, webServiceKey_) {
// Lookup the requested web service URL
var url = https://documentlookup.com:8443/getmydocuments;
// Create the AJAX request.
$_.ajax({
data: data_,
method: "GET",
url: url
})
.success(done_)
.error(fail_);
};
// If the JSON data was returned with content type of "text/plain", parse as JSON before returning.
this.convertResponse = function (data_, jqXHR_) {
return (typeof(data_) === "object" ? data_ : JSON.parse(data_));
};
Basically there is a list of rows displayed in a jqxgrid(not mentioned in the code above), when a user clicks on it
$("#mydoclist").on('rowclick gets called , which calls the following function:
getMyDocumentContents function: This function basically passes the doc_id inside data variable which is made
available for the following function:
processContent:
In this function, I am trying to show in jqxPanel the value of the contentwhich is in my_document_list array.
Problem I am facing inside this function:
As can be seen, there are debugger I placed at various places which are currently commented except at one place
which is just below this line loadComplete: function (records) {
I don’t get any error above this line var dataAdapter = new $.jqx.dataAdapter(source, { , however, as soon as
I place it inside it, I get the following error:
Uncaught TypeError: Cannot use ‘in’ operator to search for ‘length’ in jquery-1.11.1.js:583
Where length is a numerical number which keeps on changing depending upon the length of value of content in the above JSON response.
Could anyone tell me what’s going wrong? thanks in advance !
Just in case needed, here is the jQuery line #583 isArraylike function :
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
if ( obj.nodeType === 1 && length ) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj; // THIS is LINE 583 which throws error
}
Should I try changing the jQuery version?
At data_.my_document_list.length[0].content; I think you need data_.my_document_list[0].content;.
my_document_list is an array and as such the array access should occur there.
I am making an ajax call in my javascript submit function. In this ajax call, I am passing an array(globalSelection) as data to the servlet. This array consists elements of function textSelection which is also pasted below.
globalSelection =[];
function submit() {
console.log("globalSelection start")
console.log(globalSelection)
console.log("globalSelection end")
$.ajax({
async : false,
type : "POST",
url : 'http://example.com:8080/myApp/DataServlet',
data: {globalSelection:globalSelection},
success : function(data) {
alert(data)
},
error : function(data, status, er) {
alert("error: " + data + " status: " + status + " er:" + er);
}
});
}
function textSelection(range, anchorNode, focusNode) {
this.range = range;
this.type = 3;
this.rCollection = [];
this.textContent = encodeURI(range.toString());
this.anchorNode = anchorNode;
this.focusNode = focusNode;
this.selectionId = getRandom();
this.yPOS = getYPOS();
this.getTagName = function(range) {
var el = range.startContainer.parentNode;
return el;
}
this.getTagIndex = function(el) {
var index = $(el.tagName).index(el);
return index;
}
this.simpleText = function(node, range) {
if (!node)
var entry = this.createEntry(this.anchorNode, this.range);
else
var entry = this.createEntry(node, range);
this.rCollection.push(entry);
this.highlight(this.rCollection[0].range);
this.crossIndexCalc();
textSelection._t_list.push(this);
pushto_G_FactualEntry(this);
}
this.compositeText = function() {
this.findSelectionDirection();
var flag = this.splitRanges(this.anchorNode, this.focusNode,
this.range.startOffset, this.range.endOffset);
if (flag == 0) {
for (j in this.rCollection) {
this.highlight(this.rCollection[j].range);
}
}
this.crossIndexCalc();
textSelection._t_list.push(this);
pushto_G_FactualEntry(this);
}
}
I am ading the screen of my browser console below, which prints the globalSelection(array).
In my servlet I am getting this array as follows
String[] arrays = request.getParameterValues("globalSelection[]");
System.out.println(arrays);
Here I am getting null value for arrays.
If I put globalSelection as follows in submit function for simple test to servlet, I am able to get the arrays.
var globalSelection = ["lynk_url", "jsonBody", "lynk_dummy1", "lynk_dummy2", "lynk_name", "lynk_desc", "lynk_flag"];
Why my actual globalSelection is shows null in servlet, what I am doing wrong here.
Try with :
String[] arrays = request.getParameterValues("globalSelection");
System.out.println(arrays);
Because the parameter submitted with name "globalSelection" only not "[]" symbol.
I see your problem and I have a simple solution.
I recommend in that case that you convert the array as a string in JS:
JSON.stringify(globalSelection)
and then reconstructing the object on the backend using some sort of library for JSON conversion like: https://code.google.com/archive/p/json-simple/
You could then do something like this:
JSONArray globalSelection = (JSONArray) new JSONParser().parse(request.getParameter("globalSelection"));
Iterator i = globalSelection.iterator();
while (i.hasNext()) {
JSONObject selection = (JSONObject) i.next();
String type = (String)selection.get("type");
System.out.println(type);
}
This will parse your array and print the selection type. Try it, hope it helps.
I am getting a very strange issue whereby when I try to extract the word document as a compressed file for processing in my MS Word Task Pane MVC app the third time, it will blow up.
Here is the code:
Office.context.document.getFileAsync(Office.FileType.Compressed, function (result) {
if (result.status == "succeeded") {
var file = result.value;
file.getSliceAsync(0, function (resultSlice) {
//DO SOMETHING
});
} else {
//TODO: Service fault handling?
}
});
The error code that comes up is 5001. I am not sure how to fix this.
Please let me know if you have any thoughts on this.
Additional Details:
From MSDN:
No more than two documents are allowed to be in memory; otherwise the
getFileAsync operation will fail. Use the File.closeAsync method to
close the file when you are finished working with it.
Make sure you call File.closeAsync before you read the file again - that could explain the issue you are seeing.
More at: https://msdn.microsoft.com/en-us/library/office/jj715284.aspx
I have an example about how to use this API correctly. Actually the current example in the MSDN is not very correct. This code is tested in Word.
// Usually we encode the data in base64 format before sending it to server.
function encodeBase64(docData) {
var s = "";
for (var i = 0; i < docData.length; i++)
s += String.fromCharCode(docData[i]);
return window.btoa(s);
}
// Call getFileAsync() to start the retrieving file process.
function getFileAsyncInternal() {
Office.context.document.getFileAsync("compressed", { sliceSize: 10240 }, function (asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
document.getElementById("log").textContent = JSON.stringify(asyncResult);
}
else {
getAllSlices(asyncResult.value);
}
});
}
// Get all the slices of file from the host after "getFileAsync" is done.
function getAllSlices(file) {
var sliceCount = file.sliceCount;
var sliceIndex = 0;
var docdata = [];
var getSlice = function () {
file.getSliceAsync(sliceIndex, function (asyncResult) {
if (asyncResult.status == "succeeded") {
docdata = docdata.concat(asyncResult.value.data);
sliceIndex++;
if (sliceIndex == sliceCount) {
file.closeAsync();
onGetAllSlicesSucceeded(docdata);
}
else {
getSlice();
}
}
else {
file.closeAsync();
document.getElementById("log").textContent = JSON.stringify(asyncResult);
}
});
};
getSlice();
}
// Upload the docx file to server after obtaining all the bits from host.
function onGetAllSlicesSucceeded(docxData) {
$.ajax({
type: "POST",
url: "Handler.ashx",
data: encodeBase64(docxData),
contentType: "application/json; charset=utf-8",
}).done(function (data) {
document.getElementById("documentXmlContent").textContent = data;
}).fail(function (jqXHR, textStatus) {
});
}
You may find more information from here:
https://github.com/pkkj/AppForOfficeSample/tree/master/GetFileAsync
Hope this could help.
Additional to Keyjing Peng's answer (which I found very helpful, thanks!) I thought I'd share a variation on the encodeBase64, which you don't want to do if you are uploading via REST to SharePoint. In that case you want to convert the byte array to a Uint8Array. Only then could I get it into a SharePoint library without file corruption.
var uArray = new Uint8Array(docdata);
Hope this helps someone, couldn't find this info anywhere else online...
See this link
http://msdn.microsoft.com/en-us/library/office/jj715284(v=office.1501401).aspx
it contains this example method:
var i = 0;
var slices = 0;
function getDocumentAsPDF() {
Office.context.document.getFileAsync("pdf",{sliceSize: 2097152}, function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then
// result.value will return a valid File Object.
myFile = result.value;
slices = myFile.sliceCount;
document.getElementById("result").innerText = " File size:" + myFile.size + " #Slices: " + slices;
// Iterate over the file slices.
for ( i = 0; i < slices; i++) {
var slice = myFile.getSliceAsync(i, function (result) {
if (result.status == "succeeded") {
doSomethingWithChunk(result.value.data);
if (slices == i) // Means it's done traversing...
{
SendFileComplete();
}
}
else
document.getElementById("result").innerText = result.error.message;
});
}
myFile.closeAsync();
}
else
document.getElementById("result2").innerText = result.error.message;
});
}
change "pdf" to "compressed" and the method call doSomethingWithChunk() needs to be created and should probably do something like this:
function base64Encode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
I use this technique to successfully save to Azure blob storage.
Obviously you should rename the method as well.