How to access RESTlet SuiteScript parameters using GET method - javascript

I was stuck on a problem which probably plenty of new SuiteScript hackers will.
As writted on the official doc of SuiteScript p. 243, there's this JS for retrieve a record with GET method.
// Get a standard NetSuite record
function getRecord(datain) {
return nlapiLoadRecord(datain.recordtype, datain.id); // e.g recordtype="customer", id="769"
}
// http://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=22&deploy=1&recordtype=customer&id=769
But, when I was trying the EXACT snippet on NetSuite side, datain.recordtypewas undefined. (and return should only return text, BTW.)
Fortunately, I've found the solution by myself. Check my answer below.

In this snippet (the same as above) ...
function getRecord(datain) {
return nlapiLoadRecord(datain.recordtype, datain.id); // e.g recordtype="customer", id="769"
}
// http://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=22&deploy=1&recordtype=customer&id=769
—
SuiteScript was filling datain not as an object nor JSON but as a string (for reason I still ignore.)
What you have to do so is just parse it before, then access the JSON with dot notation.
function getRecord(datain) {
var data = JSON.parse(datain); // <- this
return "This record is a " + data.recordtype + " and the ID is " + data.id;
}
// http://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=22&deploy=1&recordtype=customer&id=769
I've changed the return statement in the solution because SuiteScript gives me error when I try to return something what isn't a text.
OR
As egrubaugh360 said, specify the Content-Type is application/json on your query script (the one who make call to your SuiteScript script)
So it'll give something like this if you're dealing with Node.js like me :
var options = {
headers: {
'Authorization': "<insert your NLAuth Authentification method here>",
"Content-Type" : "application/json" // <- this
}
}
https.request(options, function(results) {
// do something with results.
}
Hope this will help someone.

Related

Parsing XML file using only built-in JavaScript functions

I'm a beginner in coding and I'm trying to parse an XML file, hosted on GitHub, using JavaScript, to extract, for instance, the information contained in the <author> node nested in the <book id="bk102"> node.
I'm aware there are several similar questions in Stackoverflow, I read many of them but what I am trying to do is to extract data from the above-mentioned XML file, using only built-in JavaScript functions.
Honestly, I don't know if it is even possible but I'll explain a bit more in details what I tried to do in order to give you the whole picture.
Why I can use only JS built-in functions?
I'm developing a dynamic survey form using a data collection platform called Fulcrum.
Fulcrum allows to write JavaScript code (with some custom functions) in its 'Data events' module in order to interact with the fields and calculations contained in the survey form itself.
The 'Data events' module in Fulcrum doesn't allow me to install additional packages. For this reason, I cannot install, for example, xml-js library, as suggested here, to use the built-in JavaScript JSON functions or I cannot use DOMParser() interface, among others, since Fulcrum wouldn't recognize it.
From where I started?
Reading Fulcrum documentation, I found out I can use a custom function called REQUEST and I referred to the following example. The Fulcrum custom functions are identified with CAPITAL LETTERS.
// This example looks up the place name from OpenStreetMap when the location changes and fills in a text
// field with the place name. Replace 'place_name' below with a text field on your form.
ON('change-geometry', function(event) {
var options = {
url: 'https://nominatim.openstreetmap.org/search/' + LATITUDE() + ',' + LONGITUDE(),
qs: {
format: 'json',
polygon: 1,
addressdetails: 1
}
};
REQUEST(options, function(error, response, body) {
if (error) {
ALERT('Error with request: ' + INSPECT(error));
} else {
var data = JSON.parse(body);
if (data.length) {
SETVALUE('place_name', data[0].display_name);
}
}
});
});
The only issue here is that this example reads form a JSON file, while I need to read from a XML file.
What I tried?
I tried to edit the function in the example to make it work with an XML file. This is how I modified it.
ON('click', 'import_xml', function(event) {
var options = {
url: 'https://gist.githubusercontent.com/Ram-N/5189462/raw/46db0b43ad7bf9cbd32a8932f3ab981bd4b4da7c/books.xml',
qs: {
format: 'xml'
}
};
REQUEST(options, function(error, response, body) {
if (error) {
ALERT('Error with request: ' + INSPECT(error));
} else {
var data = body;
if (data.length) {
SETVALUE('test_field_xml', data);
}
}
});
});
And it works! Partially... When I click the import_xml hyperlink (refer to 1 below), I'm able to import the whole body of the XML file in the test_field_xml field (refer to 2 below) but I dont' really know how to extract only the information contained in the <author> node nested in the <book id="bk102"> node.
Any advice on how to proceed would be extremely helpful. Thank you, Stefano.
EDIT1:
I think I found a very "homemade" and partial solution, also not very practical or nice but it works. I edited the code above as shown below:
ON('click', 'import_xml', function(event) {
var options = {
url: 'https://gist.githubusercontent.com/Ram-N/5189462/raw/46db0b43ad7bf9cbd32a8932f3ab981bd4b4da7c/books.xml',
qs: {
format: 'xml'
}
};
REQUEST(options, function(error, response, body) {
if (error) {
ALERT('Error with request: ' + INSPECT(error));
} else {
var data = body;
var test1 = body.substring(
body.lastIndexOf('<book id="bk102">') + 24,
body.lastIndexOf('<book id="bk103">') - 15
);
var test2 = test1.substring(
test1.lastIndexOf('<author>') + 8,
test1.lastIndexOf('</author>') - 0
);
if (data.length) {
SETVALUE('test_field_xml', test2);
}
}
});
});
In your opinion, could this be done in a better and more efficient way?
You have said you are allowed to write Javascript code, but that you can't install additional Javascript packages. So the answer is to download an open-source XML parser written in Javascript and add it to your code as if it was part of the code you had written yourself.

How can I redirect with extra information in jquery?

I'd like to perform a redirect, but I also wish to send additional information along with it.
I've tried to change the value of window.location.href but that doesn't seem to pass along the extra information.
I also get how I can do
$.get(
new_url,
{data : "mydata"},
function(data) {
alert('page content: ' + data);
}
);
and that will display the html content of the new page, but that doesn't help with actually getting there.
How can I achieve this?
Edit: I feel as if I must be phrasing this terribly because I'm pretty sure this is an easy/common task. This shouldn't be something that would require cookies - it should basically be like a post request (I think).
You have a few different options for this:
URI Variables - You can append extra data to the URL by appending a question mark (?) followed by a set of key-value separated by an ampersand (=) with each variable being separated by an ampersand (&). For instance, http://www.google.com/search?q=javascript+url+variables&ie=UTF-8 gives you a link to a Google search for "javascript url variables" using UTF-8 encoding. Your PHP code or JavaScript would need to handle passing along and processing these variables. If using JavaScript a nice library for processing URLs is URI.js or using PHP you can use the parse_url and http_build_query functions. You can use this with window.location.href; for instance: window.location.href = "http://www.google.com/search?q=javascript+url+variables&ie=UTF-8" (replace the Google URL with the one you created or set in a variable).
Storage API - You can use the localStorage or sessionStorage properties to store and retrieve information using JavaScript (information is stored in the user's browser - supported by IE 8 and newer and all other major browsers). Note that this is JavaScript only unless you grab the data with JavaScript and pass it to your PHP server through URL variables, form, AJAX request, etc.
Cookie - You can store additional information inside a cookie - however this is more difficult since you have to setup your variables as a parsable string (possibly JSON) and remember to encode/decode the string when setting/getting the cookie. I don't recommend this method.
IndexedDB API - This is a more advanced client-side/browser storage mechanism and currently only supported in IE 10 and newer (and nearly all other browsers). There are also still changes being made to the standard which means newer versions of browsers could break current implementations or be buggy. If all you need is simple key-value storage (not an SQL-like database) then you should stick with one of the above options.
You can use the window open method to redirect your user,and remember to use "_self"
window.open('url','_self');
Preferably you'd store the data in localStorage and fall back to a cookie (I really like js-cookie).
Here are the two helper functions you need to store and retrieve data:
function setMultiPageData(itemName, data) {
var dataStr = JSON.stringify(data);
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
localStorage.setItem(itemName, dataStr);
}
else {
Cookies.set(itemName, dataStr, { path: '/' }); // path set to root to make cookie available on any page
}
}
function getMultiPageData(itemName) {
var data = null;
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
data = localStorage.getItem(itemName);
}
if (!hasLocalStorage || data === null) {
data = Cookies.get(itemName);
}
var parsedObject = null;
try {
parsedObject = JSON.parse(data);
}
catch (ex) {
console.log(ex); // remove in production
}
return parsedObject;
}
usage:
var data = { first: 'this is the first thing', second: 'this is the second thing' };
setMultiPageData('stackoverflow-test', data);
// go to a new page
var retrievedData = getMultiPageData('stackoverflow-test');
if (retrievedData === null) {
console.log('something went wrong')
}
else {
console.log(retrievedData); // { first: 'this is the first thing', second: 'this is the second thing' }
}

Accessing JSON parsed object

So here is my JS code:
$(document).ready(function() {
$.ajax({
url: "/",
type:"POST",
beforeSend: function (xhr) {
var token = $('meta[name="csrf_token"]').attr('content');
if (token) {
return xhr.setRequestHeader('X-CSRF-TOKEN', token);
}
},
success:function(data){
console.log(data);
},error:function(){
console.log("error!!!!");
}
});
});
And this is what I get in my console:
Object { all_creations: "[{"id":"2","user_id":"2","title":"D…" }
But now I'd like to do something like:
console.log(data.user_id)
But this return nothing..
Same for:
console.log(data['all_creations'].user_id)
console.log(data['all_creations'][0].user_id)
console.log(data[0].user_id)
...
I am using laravel5 btw and this JSON object is return by the toJson() function. (if this is any help)
I know this question has already been answered millions times but for some reason I cannot get it work on my project... I am not a pro in Javascript or anything related to it like JSON. Ajax, JSON remain for me a source of intense pain. I hope to get it one day... seriously ^^
If anything, this is a rough guide to how you can access your data:
Object { all_creations: "[{"id":"2","user_id":"2","title":"D…" }
^^^^^^^^ ^
The marked areas indicate that data is a standard object, so it has already been parsed.
Object { all_creations: "[{"id":"2","user_id":"2","title":"D…" }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The inner portion says that data.all_creations is a property that contains a string value.
Object { all_creations: "[{"id":"2","user_id":"2","title":"D…" }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The string value itself seems to contain a JSON encoded value, so you would need to parse that first:
var creations = JSON.parse(data.all_creations);
Then, from the string value you can see it contains an array with an object as the first element.
alert(creations[0].user_id) // 2
I feel like your best bet here would be to test it in Chrome and use the F12 developer tools to see what is coming back from the server. Maybe check the request in the Network tab or try to figure out the proper way to retrieve the user_id in the console.
If confused take a look at some F12 Chrome developer tools tutorials.

AngularJS and Jersey REST DELETE operation fails with 415 Status code

I have a AngularJS webapplication with a Jersey Backend Application.
Now everything is working fine using ngResource to access REST resource out of AngularJS. The only problem is with the DELETE option.
I have the following code to delete a course using my ngResource:
Course.deleteCourse = function(course) {
course.$remove({
courseId:course.id
});
return course;
};
In the backend (Jersey) I have the following code:
#DELETE
#Path("{id}")
public final void remove(#PathParam("id") final String id) {
System.out.println("DELETE ID = " + id);
}
If I try to delete an item the following url is called from Angular:
DELETE http://localhost:8080/manager-api/courses/5
This is fine (after me). If I call this url from CURL, i get the ssystem.out from the Backend posted to the console.
In the client-app (AngularJS) i get the following exception on the browser console:
DELETE http://localhost:8080/manager-api/courses/5 415 (Unsupported Media Type)
Anyone an idea what the problem might be? POST + GET are working fine.
I have the following consume/produce annotations:
#Consumes({ MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_JSON })
Thanks in advance for your help.
Greets
Marc
EDIT:
I have tried to replace the way of accessing the REST services out of AngularJS with $http.
Now my service looks as below:
MyApp.factory("Course", ["$http", function ($http) {
var courseBaseUrl = "/api/courses/";
return {
show: function show(courseId) {
return $http.get(courseBaseUrl + courseId);
},
list: function list() {
return $http.get(courseBaseUrl, {});
},
remove: function remove(courseId) {
return $http.delete(courseBaseUrl + courseId, {});
},
save: function save(course) {
return $http.post(courseBaseUrl, course, {});
}
};
}]);
The result is still the same. The application calls e.g
DELETE http://localhost:8080/manager-api/courses/1
and receives a
DELETE http://localhost:8080/manager-api/courses/1 415 (Unsupported Media Type)
If I call the same DELETE call on Curl, everything works fine.
Thanks for your help
Marc
I came across this as well, the problem is angular always sets the Content-Type header to xml on DELETE requests and jersey will chuck an error as you have specified that your api consumes/produces JSON with the annotations.
So to fix it (from the client side), set the content-type header, eg:
.config(function($httpProvider) {
/**
* make delete type json
*/
$httpProvider.defaults.headers["delete"] = {
'Content-Type': 'application/json;charset=utf-8'
};
})
However, for reasons I dont understand/dont know of, angular will strip away the content-type header from the request if it has no data. This would make sense if it wasn't for the fact that browsers (chrome at least) will always send a content-type... Anyway you will have to go to the trouble of finding this in the angular source:
// strip content-type if data is undefined
if (isUndefined(config.data)) {
delete reqHeaders['Content-Type'];
}
and get rid of it. I dont know of a way to do this without editing the source. Maybe someone with better JS know-how, erm, knows how.
Alternatively, from the server side, you can do as Rob has suggested and change the Jersey configuration to allow consuming MediaType.APPLICATION_XML
#Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public final void remove(#PathParam("id") final String id) {
System.out.println("DELETE ID = " + id);
}
I had same issue, Try returning new instance of Course object in your delete method.
#DELETE
#Path("{id}")
public final Course remove(#PathParam("id") final String id) {
System.out.println("DELETE ID = " + id);
return new Course();
}
Using angularjs $resource (instead of $http), without "payload" in the request, the content-type is setted as text/plain.
So IMHO it's better a server side support.
"Postel's Law states that you should be liberal in what you accept and conservative in what you send. -- source"
#DELETE
#Path("{id}")
#Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN })
public void remove(#PathParam("id") Long id) { ...

LungoJS Json, fill content returned into a list

i am a Java Developer and i need to create a SIMPLE app, as i need this to run into ios & Android i decided to try it using lungoJS, my main problem is that i dont know much JavaScript.. :(
well i have created the prototipe of the app using lungo, but now i need to fill a list with the response (on Json) from my server. I saw in lungos api the function that is used to get a Json request. looks like this:
var url = "http://localhos:8080/myService";
var data = {id: 25, length: 50};
var parseResponse = function(result){
//Do something
};
Lungo.Service.json(url, data, parseResponse, "json");
//Another example
var result = Lungo.Service.json(url, "id=25&len=50", null, "json");
my http request is indexed from 1 to 4 so for each element would be "www.myapp.com/api/1" "www.myapp.com/api/2"
....
my question is, hoy could i get the answer (json) of my request and how do i select items for example if i only want the "name" or "surname"...
thanks, hope some1 could help me :)
I solved my problem long time ago, i will share it:
function some_function(callback) {
var my_number = $$.get('http://app.com/applications/3.json',{ }, function(api) {
obj=api;
template="{{#name}}\
\
{{/name}}";
html=Mustache.render(template,obj);
$$('section#main article#main-article').html(html); //Painting Json obtained on my HTML
}
);
;
callback(my_number);
}
// call the function
some_function(function(num) {
// this anonymous function will run when the
// callback is called
console.log("callback called! " + num);
});
This code uses the obtained Json to Prototype HTML, useful to load images or data from server and not stored on local.
BR, Kike

Categories