javascript help - doing something new in a old school way - javascript

UPDATE :
Some have said that they were able to get more than 1 childNode...
Here is my fiddle - I am only getting 1 childNode to display.
Where is the error?
ORIGINAL Question
Below is a partial snippet of javascript code that I have inherited. Basically this function used to get XML data by calling an AJAX function. However, due to requirement changes I am generating an XML string and storing that string in hidden input variable on the screen (Classic ASP).
After looking closer at the original script I found that it would be nice if I could somehow pass my xml string into the cmdxml variable. However, when I set cmdxml equal to my xml string: cmdxml = $.parseXML(xmlVal); and then try to use the snippet below it only gets 1 child node. I've included a small snippet of the xml string that I'm passing below.
Old Javascript Function (partial) using cmdxml:
if (req.responseXML!=null) {
var PropName;
var PropValue;
var cmdxml = req.responseXML.documentElement;
// read each document element child node in the XML document
for (var c =0;c<cmdxml.childNodes.length;c++) {
var m;
var t = cmdxml.childNodes[c]; //req.responseXML.documentElement.childNodes[c]
if (t!=null) {
//console.log(t.nodeName);
switch(t.nodeName) { //req.responseXML.documentElement.childNodes[c].nodeName
case "RObject": { //response object
var RObject = t;
//req.responseXML.documentElement.childNodes[c].nodeName.attributes[2].value
var CtrlChangeType = RObject.attributes[2].value;
var CtrlObjName = RObject.attributes[1].value;
var CtrlObjType = RObject.attributes[0].value;
var CtrlObj;
var RObjProp = RObject.getElementsByTagName("Property");
PropName = RObjProp[0].attributes[0].value;
PropValue = getElementText(RObjProp[0].getElementsByTagName("Value")[0]);
switch (CtrlChangeType) { //req.responseXML.documentElement.childNodes[c].nodeName.attributes[0].value
case "comboboxInsRow": {
Here is a snippet of my xml string that I'm passing:
<?xml version="1.0" ?><xCMDS><JCallBack ProgramName="x"><Value><![CDATA[top.closeCtrlLoading();]]></Value></JCallBack><RObject Type="E" Name="gH2ptObj_co_code" ChangeType="objProp" rowNum="" colNum=""><Property Name="value"><Value><![CDATA[]]></Value></Property></RObject>

parseXML returns an XMLDocument, . You'll need to set cmdxml zo $.parseXML('snippet').documentElement to access the childNodes(childNodes is a property of nodes, usually not available in documents) .
Your fiddle returns a childNode, but this is the root-element, you like to access the childNodes of the root-element.

Related

Content not allowed in prolog - XML Document Post

I am trying to create an xml document to send via a POST request. However, I am getting this error on the server side :
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
I think it may be because I am missing
<?xml version="1.0" encoding="UTF-8"?>
However I am unsure on the correct way to implement it. If anyone has any ideas that would great !
export function jsToXML(film, crudOp) {
//Creating Document and elements
var xmlDoc = document.implementation.createDocument(null, "film");
const xmlVersion = '<?xml version="1.0"?>';
var title = xmlDoc.createElement("title");
var year = xmlDoc.createElement("year");
var director = xmlDoc.createElement("director");
var stars = xmlDoc.createElement("stars");
var review = xmlDoc.createElement("review");
//Edit & Delete CRUD Operations need ID
if (crudOp === "edit" || crudOp === "delete") {
var id = xmlDoc.createElement("id");
id.append(film.id);
xmlDoc.documentElement.appendChild(id);
}
//Assign form data to elements
title.append(film.title);
year.append(film.year);
director.append(film.director);
stars.append(film.stars);
review.append(film.review);
//Append the elements to the xml doc
xmlDoc.documentElement.appendChild(title);
xmlDoc.documentElement.appendChild(year);
xmlDoc.documentElement.appendChild(director);
xmlDoc.documentElement.appendChild(stars);
xmlDoc.documentElement.appendChild(review);
return xmlDoc;
}
There's a very wide variety of possible causes: see org.xml.sax.SAXParseException: Content is not allowed in prolog for some of them. Omitting the XML declaration isn't one of those causes.
This is generally a message from the Java XML parser, so I'm not sure where your Javascript code (for constructing an XML tree) fits in.
To fix this I added a serializer as .createElement(Item), creates a HTML Node.
//Serialize xml dom
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(xmlDoc);
return xmlString;
This is what I added to solve the problem

Google Appscript: Output of parsing function for a Table of Contents results in an array of objects not in the correct format. Help appreciated

I am currently trying to parse the url and text from a table of contents on a google doc and write them into a table on google sheets.
So far I have been successful in getting the text and the url using the following code modified from the top answer in this post (How to use .findElement(DocumentApp.ElementType.TABLE_OF_CONTENTS) to get and parse a Document's Table of Contents Element)
function parseTOC( docId ) {
var contents = [];
var doc = DocumentApp.openById(docId);
// Define the search parameters.
var searchElement = doc.getBody();
var searchType = DocumentApp.ElementType.TABLE_OF_CONTENTS;
// Search for TOC. Assume there's only one.
var searchResult = searchElement.findElement(searchType);
if (searchResult) {
// TOC was found
var toc = searchResult.getElement().asTableOfContents();
// Parse all entries in TOC. The TOC contains child Paragraph elements,
// and each of those has a child Text element. The attributes of both
// the Paragraph and Text combine to make the TOC item functional.
var numChildren = toc.getNumChildren();
for (var i=0; i < numChildren; i++) {
var itemInfo = {}
var tocItem = toc.getChild(i).asParagraph();
var tocItemAttrs = tocItem.getAttributes();
var tocItemText = tocItem.getChild(0).asText();
// Set itemInfo attributes for this TOC item, first from Paragraph
itemInfo.text = tocItem.getText(); // Displayed text
// ... then from child Text
itemInfo.linkUrl= tocItemText.getLinkUrl(); // URL Link in document
contents.push(itemInfo);
}
}
// Return array of objects containing TOC info
return contents;
}
function test_parseTOC() {
var fileId = '--Doc-ID--';
var array = parseTOC(DocumentApp.getActiveDocument().getId() );
Logger.log(array)
}
The function test_parseTOC returns the following array:
[{linkUrl=#heading=h.nyq88bov1u8x, text=Google}, {text=Help, linkUrl=#heading=h.9lthewlyeqjd}]
Although the information is correct, the "=" is giving me trouble. When working with an array of objects I would expect it to be:
[{linkUrl: "#heading=h.nyq88bov1u8x", text: "Google"}, {text: "Help", linkUrl: "#heading:h.9lthewlyeqjd"}]
What I am trying to emulate can be outlined by this post here (Google Apps Script: how to copy array of objects to range?)
If I manually change the "=" to ":" and add quotation marks then the array works fine. Is there something with the original function I can change to produce a ":" instead of a "="? Or is there a way to modify the array of objects after the fact to replace the "=" with ":"? I could easily use concat to automatically add the quotation marks, but the "=" is out of my wheelhouse.
Thank you for any input on this
Update: It actually turns out that this code was working appropriately and I was receiving an error from a different function that was using the output of this one (i.e. I wrote .getSheets(0) not .getSheets()[0]. I will leave up the original post in case anyone needs a working example of how to extract out links from a TOC and along with the resources to write it to a google sheet

When stringifying an object, JSON turns element nodes into Objects?

So I'm working on a little personal project and I came upon a problem.
I need each day object to hold various dom element objects. These object instances are stored in an array and then that array needs to be stored into localStorage to load later.
The problem is when I do JSON.stringify and then JSON.parse it converts the HTML nodes into objects. So when I try to append element it tells me that the first parameter is not a node.
function save() {
localStorage.days = JSON.stringify(global.days);
localStorage.numberOfDays = global.numberOfDays;
localStorage.totalCount = global.totalCount;
}
function load() {
var parsedDays = JSON.parse(localStorage.days);
parsedDays.forEach(function(day){
document.getElementById("mainPage").appendChild(day.textObject);
});
anyone know how I can put an array of objects which hold elements into localStorage while keeping their node type????
If you will try to stringify dom nodes then it will return "{}".So its not possible to store node as it is inside localstorage.
What you can do is store information regarding nodes inside localstorage and recreate your node from that information and add it in your dom.
You'd probably need to have a property eg 'type' that defines the element type
var elem
parsedDays.forEach(function(day){
elem = document.getElementById("mainPage").createElement(day.type);
elem.attributes = day.attributes;
elem.innerHTML = day.textObject;
});
Or something like that, not too sure without seeing your day object
Use JSON.stringify and JSON.parse
Example Code:
Element.prototype.toJSON = function (){
return {nodeType:this.nodeType, outerHTML:this.outerHTML};
};
function replacer(k,v){
if(v.nodeType===1 && v.outerHTML){
var ele = document.createElement('html');
ele.innerHTML = v.outerHTML;
return ele.removeChild(ele.firstChild);
}
return v;
}
//test
var jstr = JSON.stringify({ele:document.body});
var json = JSON.parse(jstr,replacer);
console.log(jstr);
console.log(json);

Javascript Form: Only Changed Fields

I have a php-site with a form on which i output preselected values via php. On form submit I want to check which values have changed and just submit these via javascript.
These are the preselected values I passed over from php. It's important that I keep the associative array structure.
var pbData = jQuery.parseJSON("{
"GameMode":"DEATHMATCH",
"Current Map":"VEGAS JUNKYARD",
"Current Missions":["VEGAS JUNKYARD","VILLA","PRESIDIO","KILL HOUSE","MURDERTOWN","CQB TRAINING","STREETS","THREE KINGDOMS CASINO","IMPORT\/EXPORT;"],
"RoundDuration":"3 minutes"}");
I marked the error in the code.
<script>
function displayVars(){
var form = document.getElementById('settings');
var elems = form.elements;
var txt = "";
for (var index = 0; index < elems.length; index++){
var selIndex = elems[index].selectedIndex;
if (typeof selIndex !== "undefined"){
//the Index Name in the json-object and the name of the form-field are the same
var idxName = elems[index].name;
//HERE is the problem. I want to access the subobject via a variablename, so i can iterate through it, but that doesnt work.
console.log ("pbData default = "+pbData.idxName); //always undefined
if (elems[index].value !== pbData.idx_name){
//building a POST-Url
txt = txt + elems[index].name + "=" + elems[index].options[selIndex].value+"&";
}
}
}
console.log (txt);
return false;
}
</script>
I know that I could do this differently, also with jQuery. In my case as I have the preselected values as a php-variable in any case, i think it's easier like this.
I would really like to know how I can iterate through the subobjects via a variable that contains the object names.
This is due to how you'e trying to access the property of the (JSON) object. Consider
var o1 = {idxName: true},
o2 = {foo : 'bar'},
idxName = 'foo';
o1.idxName; // true
o2.idxName; // undefined
o2[idxName]; // 'bar'
You need to access the property via pbData[idxName].
Additionally, you're not escaping quotes in your JSON string, and line breaks need to be escaped as follows
var pbData = jQuery.parseJSON("{\
\"GameMode\":\"DEATHMATCH\",\
\"Current Map\":\"VEGAS JUNKYARD\",\
\"Current Missions\":[\"VEGAS JUNKYARD\",\"VILLA\",\"PRESIDIO\",\"KILL HOUSE\",\"MURDERTOWN\",\"CQB TRAINING\",\"STREETS\",\"THREE KINGDOMS CASINO\",\"IMPORT\/EXPORT;\"],\
\"RoundDuration\":\"3 minutes\"}");
In Javascript you could keep an object or array with initial values and only post those values that are changed.
But in fact, I would do something similar, but in PHP. You can keep the original values in the session and compare the posted values to those initial values to see what has changed. That way, you won't depend on Javascript. Not only may Javascript be disabled, but also, a fast user may theoretically post the form before the Javascript has run. To move this check to PHP eliminates that risk.

Issue with JSON stringify?

/* Helper function to clean up any current data we have stored */
function insertSerializedData(ids, type) {
// Get anything in the current field
current_data = $('#changes').val();
if (!current_data) {
var data = new Array();
data[type] = ids;
$('#changes').val(JSON.stringify(data));
} else {
var data = JSON.parse($('#changes').val());
data[type] = ids;
$('#changes').val(JSON.stringify(data));
}
console.log($('#changes').val());
}
I am using the following function to either add data to a current JSON object or create a new JSON object all together to be used in PHP later. Is the stringify() method only for FF? I am using google chrome and I am being given an empty object when using the conosole.log() function...
Also what happens if you try to store two values with the same key? I assume it will overwrite...so I should add a random math number at the end array in order to keep duplicates from showing up?
Thanks :)
These lines may cause problems:
var data = new Array();
data[type] = ids;
... because arrays in JavaScript are not quite like arrays in PHP. I suppose what you meant is better expressed by...
var data = {};
data[type] = ids;
Besides, current_data seems to be local to this function, therefore it also should be declared as local with var. Don't see any other problems... except that similar functionality is already implemented in jQuery .data() method.
UPDATE: here's jsFiddle to play with. ) From what I've tried looks like the array-object mismatch is what actually caused that Chrome behavior.
I reformatted it a bit, but and this seems to work. It will set the "value" attribute of the #changes element to a JSON string. I assume that the type argument is supposed to be the index of the array which you're trying to assign?
function insertSerializedData(ids, type) {
var changes = jQuery('#changes'), arr, val = changes.val();
if (!val) {
arr = [];
arr[type] = ids;
changes.val(JSON.stringify(arr));
} else {
arr = JSON.parse(val);
arr[type] = ids;
changes.val(JSON.stringify(arr));
}
console.log(changes);
}

Categories

Resources