Null Pointer exception in JavaScript - javascript

var Obj = {
StateValues: ['AL','AK','AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN','IA',
'KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND',
'OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VT','VA','WA','WV','WI','WY'],
getItemRow: function(itemValue) {
var myPosition=-1
for (var i=0;i<Obj.StateValues.length;i++) {
if(Obj.StateValues[i]==itemValue) {
myPosition = i;
break;
}
}
return myPosition;
}
}
When i add the function in the code, i get Null Pointer Expection. This piece of code is in a sep file... somename.js and which i include
I am not even using this function anywhere in my other js file... like Obj.getItemRow()

var Obj = new function(){
var StateValues = ['AL','AK','AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN','IA',
'KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND',
'OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VT','VA','WA','WV','WI','WY'];
this.getItemRow = function(itemValue) {
var myPosition=-1
for (var i=0;i<StateValues.length;i++) {
if(StateValues[i]==itemValue) {
myPosition = i;
break;
}
}
return myPosition;
};
}
This is an easier way to create objects.
var blah = 'this is private'
this.blah = 'this is public'

This works for me:
console.debug(Obj.getItemRow("AK"));

Related

How to convert xml to JSON in suitescript 2.0

I have an XML response that i want to convert it to JSON, i'm currently usingg XPath
var responseNode = xml.XPath.select({
node : xmlDocument,
xpath : '//SOAP-ENV:Envelope'
});
and it is not very efficient because to extract data from one xml tag, i have to write a lot of extra code. I tried using external libs with suitescript but they didn't worked. Is there any better way to convert XML to JSON
I have a project that needs to convert xml to json rencently, so I wrote the following function.
require(['N/xml'], function (xmlMod) {
//This function refer to https://davidwalsh.name/convert-xml-json
function xmlToJson(xmlNode) {
// Create the return object
var obj = Object.create(null);
if (xmlNode.nodeType == xmlMod.NodeType.ELEMENT_NODE) { // element
// do attributes
if (xmlNode.hasAttributes()) {
obj['#attributes'] = Object.create(null);
for (var j in xmlNode.attributes) {
if(xmlNode.hasAttribute({name : j})){
obj['#attributes'][j] = xmlNode.getAttribute({
name : j
});
}
}
}
} else if (xmlNode.nodeType == xmlMod.NodeType.TEXT_NODE) { // text
obj = xmlNode.nodeValue;
}
// do children
if (xmlNode.hasChildNodes()) {
for (var i = 0, childLen = xmlNode.childNodes.length; i < childLen; i++) {
var childItem = xmlNode.childNodes[i];
var nodeName = childItem.nodeName;
if (nodeName in obj) {
if (!Array.isArray(obj[nodeName])) {
obj[nodeName] = [
obj[nodeName]
];
}
obj[nodeName].push(xmlToJson(childItem));
} else {
obj[nodeName] = xmlToJson(childItem);
}
}
}
return obj;
};
var str = '<?xml version="1.0"?><ALEXA VER="0.9" URL="davidwalsh.name/" HOME="0" AID="="><SD TITLE="A" FLAGS="" HOST="davidwalsh.name"><TITLE TEXT="David Walsh Blog :: PHP, MySQL, CSS, Javascript, MooTools, and Everything Else">Hello World</TITLE><LINKSIN NUM="1102">Netsuite</LINKSIN><SPEED TEXT="1421" PCT="51"/></SD><SD><POPULARITY URL="davidwalsh.name/" TEXT="7131"/><REACH RANK="5952"/><RANK DELTA="-1648"/></SD></ALEXA>';
var xmlObj = xmlMod.Parser.fromString({
text: str
});
var jsonObj = xmlToJson(xmlObj.documentElement);
log.debug('jsonObj', jsonObj);
});
The cenvert function referred to David Walsh's function located at: https://davidwalsh.name/convert-xml-json
I just revised it compatible with Netsuite.
Hope it works for you.
Here's a sample function from my NetSuite environment. I did not write this,but it is currently working.
//*********** PARSE XML INTO JSON ***********
function nsXMLToJSON(node){
var obj=nsXMLToJSONDirty(node);
var cleanObj=cleanObject(obj,true);
return cleanObj;
//*********** HELPER FUNCTIONS ***********
function nsXMLToJSONDirty(node){
var obj={};
if(!'nodeType' in node){
return obj;
}
if(node.nodeType==1 || node.nodeType=='ELEMENT_NODE'){
if(Object.keys(node.attributes).length > 0){
obj["#attributes"]={};
for(var j in node.attributes){
var attribute=node.attributes[j];
if(attribute){
obj["#attributes"][attribute.name]=attribute.value;
}
}
}
}else if(node.nodeType==3 || node.nodeType=='TEXT_NODE'){
obj=node.nodeValue;
}
if(node.hasChildNodes()){
var childNodes=node.childNodes;
for(var k in childNodes){
var item=childNodes[k];
var nodeName=item.nodeName;
if(typeof (obj[nodeName])=="undefined"){
obj[nodeName]=nsXMLToJSONDirty(item); //run the function again
}else{
if(typeof (obj[nodeName].push)=="undefined"){
var old=obj[nodeName];
obj[nodeName]=[];
obj[nodeName].push(old);
}
obj[nodeName].push(nsXMLToJSONDirty(item));
}
}
}
return obj;
}
function cleanObject(myobj,recurse){
var myobjcopy=JSON.parse(JSON.stringify(myobj));
for(var i in myobjcopy){
if(recurse && typeof myobjcopy[i]==='object'){
if(i=="#text"){
delete myobjcopy[i];
} else {
//Check if it only contains a text object
if(Object.keys(myobjcopy[i]).length==1){
if(typeof myobjcopy[i]['#text'] != "undefined"){
if(myobjcopy[i]['#text'] || myobjcopy[i]['#text']==0){
myobjcopy[i]=myobjcopy[i]['#text'];
}
}
}else{
//Handle empty objects
if(Object.keys(myobjcopy[i]).length==0){
myobjcopy[i]=undefined;
}
}
if(myobjcopy[i]){
myobjcopy[i]=cleanObject(myobjcopy[i],recurse);
}
}
}
}
return myobjcopy;
}
}
create a helper.js file so the function can be shared across different scripts.
define(["N/xml"], function (xml) {
function xmlToJson(text) {
function xmlNodeToJson(xmlNode, obj) {
var sibling = xmlNode;
while (sibling) {
if (sibling.nodeType == xml.NodeType.COMMENT_NODE) {
sibling = sibling.nextSibling;
continue;
}
if (sibling.nodeType == xml.NodeType.TEXT_NODE) {
if (!!sibling.nodeValue.replace(/[\n| ]/g, ''))
obj[sibling.nodeName] = sibling.nodeValue;
sibling = sibling.nextSibling;
continue;
}
var childObj = Object.create(null);
if (!!sibling.hasAttributes()) {
Object.keys(sibling.attributes).forEach(function (key) {
childObj[key] = sibling.getAttribute({ name: key });
});
}
var value = xmlNodeToJson(sibling.firstChild, childObj);
if ((sibling.nodeName in obj)) {
if (!Array.isArray(obj[sibling.nodeName])) {
obj[sibling.nodeName] = [obj[sibling.nodeName]];
}
obj[sibling.nodeName].push(value);
} else {
obj[sibling.nodeName] = value;
}
sibling = sibling.nextSibling;
}
return obj;
}
var xmlDocument = xml.Parser.fromString({ text: text });
return xmlNodeToJson(xmlDocument.firstChild, Object.create(null));
}
return {
xmlToJson: xmlToJson
}
});
import the helper file and use the xmlToJson function in your script.
define(['N/file', '/SuiteScripts/PATH_TO_HELPER_FILE/helper'], function(file, helper) {
...
var string = file.load({ id: '/SuiteScripts/PATH_TO_FILE/filename.xml' }).getContents()
var json_object = helper.xmlToJson(string);
...
})

JavaScript variable Objects

I am very much new to Javascript
please correct my code or suggest the best option
var myApp = {};
myApp.set = function(VAL) {
myApp.id = VAL;
}
myApp.get = function() {
return myApp.id;
}
function PageLoad() {
var X = new myApp;
var Y = new myApp;
Y.set(20);
X.set(10);
alert(X.get());
alert(Y.get());
}
It shows last assign value only i.e. 10 :(
Thanks in Advance
Manoj
#Manoj Chavanke Sir Please use this code
function myApp(){
}
myApp.prototype.set = function(VAL) {
this.id = VAL;
}
myApp.prototype.get = function() {
return this.id;
}
function PageLoad() {
var X = new myApp; console.log(X);
var Y = new myApp; console.log(Y);
Y.set(20);
X.set(10);
alert(X.get());
alert(Y.get());
}
PageLoad();
I think You override the value myApp.id = VAL;
try this code
var myApp = [];
myApp.set = function(VAL) {
myApp.push({id : VAL});
}
instate of
var myApp = {};
myApp.set = function(VAL) {
myApp.id = VAL;
}
Because the key is a unique you can't use twice.

JavaScript: Prevent Array.push()

I have a sealed object with an array member on which I want to prevent direct pushes.
var myModule = (function () {
"use strict";
var a = (function () {
var _b = {},
_c = _c = "",
_d = [];
Object.defineProperty(_b, "c", {
get: function () { return _c; }
});
Object.defineProperty(_b, "d", {
get { return _d; }
});
_b.addD = function (newD) {
_d.push(newD);
};
Object.seal(_b);
return _b;
}());
var _something = { B: _b };
return {
Something: _something,
AddD: _b.addD
};
}());
myModule.Something.c = "blah"; // doesn't update = WIN!!
myModule.AddD({}); // pushed = WIN!
myModule.Something.d.push({}); // pushed = sadness
How can I prevent the push?
UPDATE:
Thanks for all the thoughts. I eventually need the JSON to send to the server. It looks like I might need to use an object for the array then figure out a way to generate and return the JSON needed, or change _something to use .slice(). Will play and report.
you could override the push method:
var _d = [];
_d.__proto__.push = function() { return this.length; }
and when you need to use it in your module, call Array.prototype.push:
_b.addD = function (newD) {
Array.prototype.push.call(_d, newD);
};
I haven't done any performance tests on this, but this certainly helps to protect your array.
(function(undefined) {
var protectedArrays = [];
protectArray = function protectArray(arr) {
protectedArrays.push(arr);
return getPrivateUpdater(arr);
}
var isProtected = function(arr) {
return protectedArrays.indexOf(arr)>-1;
}
var getPrivateUpdater = function(arr) {
var ret = {};
Object.keys(funcBackups).forEach(function(funcName) {
ret[funcName] = funcBackups[funcName].bind(arr);
});
return ret;
}
var returnsNewArray = ['Array.prototype.splice'];
var returnsOriginalArray = ['Array.prototype.fill','Array.prototype.reverse','Array.prototype.copyWithin','Array.prototype.sort'];
var returnsLength = ['Array.prototype.push','Array.prototype.unshift'];
var returnsValue = ['Array.prototype.shift','Array.prototype.pop'];
var funcBackups = {};
overwriteFuncs(returnsNewArray, function() { return []; });
overwriteFuncs(returnsOriginalArray, function() { return this; });
overwriteFuncs(returnsLength, function() { return this.length; });
overwriteFuncs(returnsValue, function() { return undefined; });
function overwriteFuncs(funcs, ret) {
for(var i=0,c=funcs.length;i<c;i++)
{
var func = funcs[i];
var funcParts = func.split('.');
var obj = window;
for(var j=0,l=funcParts.length;j<l;j++)
{
(function() {
var part = funcParts[j];
if(j!=l-1) obj = obj[part];
else if(typeof obj[part] === "function")
{
var funcBk = obj[part];
funcBackups[funcBk.name] = funcBk;
obj[part] = renameFunction(funcBk.name, function() {
if(isProtected(this)) return ret.apply(this, arguments);
else return funcBk.apply(this,arguments);
});
}
})();
}
}
}
function renameFunction(name, fn) {
return (new Function("return function (call) { return function " + name +
" () { return call(this, arguments) }; };")())(Function.apply.bind(fn));
};
})();
You would use it like so:
var myArr = [];
var myArrInterface = protectArray(myArr);
myArr.push(5); //Doesn't work, but returns length as expected
myArrInterface.push(5); //Works as normal
This way, you can internally keep a copy of the interface that isn't made global to allow your helper funcs to modify the array as normal, but any attempt to use .push .splice etc will fail, either directly, or using the .bind(myArr,arg) method.
It's still not completely watertight, but a pretty good protector. You could potentially use the Object.defineProperty method to generate protected properties for the first 900 indexes, but I'm not sure of the implications of this. There is also the method Object.preventExtensions() but I'm unaware of a way to undo this effect when you need to change it yourself
Thank you, dandavis!
I used the slice method:
var myModule = (function () {
"use strict";
var a = (function () {
var _b = {},
_c = _c = "",
_d = [];
Object.defineProperty(_b, "c", {
get: function () { return _c; }
});
Object.defineProperty(_b, "d", {
get { return _d.slice(); } // UPDATED
});
_b.updateC = function (newValue) {
_c = newValue;
};
_b.addD = function (newD) {
_d.push(newD);
};
Object.seal(_b);
return _b;
}());
var _something = { B: _b };
return {
Something: _something,
AddD: _b.addD
};
}());
myModule.Something.c = "blah"; // doesn't update = WIN!!
myModule.AddD({}); // pushed = WIN!
myModule.Something.d.push({}); // no more update = happiness
This allows me to protect from direct push calls enforcing some logic.

JavaScript: Having trouble returning custom object information

I've made some new objects with object methods and I'm having trouble returning the information.
I intend for allPages to be a 2d array:
var allPages = [[]];
function textbox(type)
{
this.type=type;
this.getInfo = function () { return ( this.type ); };
}
function addTextbox(dropdown)
{
var myindex = dropdown.selectedIndex;
var SelValue = dropdown.options[myindex].value;
if(SelValue == "String")
{
var tb = new textbox("string");
allPages[allPages.length-1].push(tb);
var string = "";
for (i = 0;i < allPages.length;i++)
{
for(j = 0;j < allPages[i].length;j++)
{
string = string + allPages[i][j].getInfo;
}
}
<!-- Problem here: prints "function () { return this.type; }"-->
document.write(string);
}
}
}
You are not calling the function, you are referencing it
allPages[i][j].getInfo;
should be
allPages[i][j].getInfo();
3 lines above where you state the problems exists, it should be:
string = string + allPages[i][j].getInfo(); // mind the () at the end.

Javascript object and this

function robot(robotId) {
this.id = robotId;
this.parts = new Array();
this.collectParts = function() {
$.getJSON('some/url', function(json) {
for(i in json.responses) {
this.parts = json.responses[i].parts;
}
});
}
}
How do I actually assign this.parts?
Assign a reference to this (when it's in the proper scope) to a variable and use that variable in the function which has changed the scope of this. In the modified version of your code below, robotInstance is the variable I've opted to use:
function robot(robotId) {
var robotInstance = this;
this.id = robotId;
this.parts = new Array();
this.collectParts = function() {
$.getJSON('some/url', function(json) {
for(i in json.responses) {
robotInstance.parts = json.responses[i].parts;
}
});
}
}
Edit: I had written this modification last night, then decided not to post it. But based on the comment to your question by #Ӫ_._Ӫ, I decided I'd show you the way I would write your code:
var robot = function( robotId )
{
this.id = robotId;
this.parts = [];
};
robot.prototype = {
collectParts: function()
{
var robotInstance = this;
$.getJSON(
'some/url',
function( json )
{
var i,
responses = json.responses;
for( i in responses )
{
if( Object.prototype.hasOwnProperty.call( responses, i ) )
{
robotInstance.parts = responses[i].parts;
}
}
}
);
}
};
To access this inside jQuery functions, you need to assign it to another variable, for instance, self = this; then replace this with self.
You can capture "this" in a "that" variable so that it can be used inside the scope of the callback of your $.getJSON
function robot(robotId) {
this.id = robotId;
this.parts = new Array();
var that = this;
this.collectParts = function() {
$.getJSON('some/url', function(json) {
for(i in json.responses) {
that.parts = json.responses[i].parts;
}
});
}
}
Just assign this to another variable e.g that
function robot(robotId) {
var that = this;
that.id = robotId;
that.parts = new Array();
that.collectParts = function() {
$.getJSON('some/url', function(json) {
for(i in json.responses) {
that.parts = json.responses[i].parts;
}
});
}
}

Categories