DOM changes in jQuery .get() success callback not reflected in page - javascript

This is my first question here and I'm totally stumped. Basically, I have a cart page that looks like this:
The site works by customers uploading images for printing, so each order is actually an image. Each cart item is generated dynamically using JS DOM functions, but the part I'm having trouble with is the row below the "Item #1" header row. It's supposed to contain a thumbnail of the order image (uploaded by the customer), which I get from a Laravel API endpoint. It returns a base64 string of the image, which I set as the image source like this:
var tbody = document.createElement('tbody');
var productImageRow = document.createElement('tr');
var productImageTD = document.createElement('td');
var productImage = document.createElement('img');
productImageTD.colSpan = 2;
if (order.productType == PRODUCT_TYPES.CONDUCTION_PLATES) {
/* Some irrelevant code here... */
} else {
$.get(<API Endpoint here>, function(data) {
productImage.src = data;
});
}
productImageTD.appendChild(productImage);
productImageRow.appendChild(productImageTD);
tbody.appendChild(productImageRow);
The problem is, even if I change the image src, it's not reflected in the browser (hence the empty row below the table header).
I am sure that the API is working because I do this exact same thing in another page and it works fine. Aside from that, if I log the base64 string in the data variable to the console and directly place it in the html like
<img src="<my base64 string>">
it displays the image fine, so I'm sure the base64 string is valid.
I also know that the success block is being executed because alerts inside it execute. When tested further, any DOM Manipulation done inside the callback doesn't get reflected in the browser. Example:
var DOMTest = document.createElement('h1');
DOMTest.innerHTML = "Before Callback";
productImageTD.appendChild(DOMTest);
...
$.get(<API Endpoint here>, function(data) {
//productImage.src = data;
DOMTest.innerHTML = "After Callback"
alert(DOMTest.innerHTML);
});
The result is that the page still displays the h1 as "Before Callback", but the alert shows the innerHTML as "After Callback". I tested this on Safari and Chrome.
I'm pretty sure I might just be making some stupid mistake. Any ideas? I'm totally lost here.

Related

Random "Cannot read properties of null" error in Google Sheet with App Script

I have a Google sheet that automatically changes the urls in cell A28 via another script. The "test()" script is called by the main script to be executed whenever the url changes. I used the code from another thread: Grab data from website HTML table and transfer to Google Sheets using App-Script.
I modified it a bit because what interested me was getting the table with the ID "pgl_basic" and actually the code works as I expected. The only problem is that, in an absolutely random way, sometimes this error is generated: "Cannot read properties of null [0]" and if I then restart the script everything is fine or it crashes before or after the url it has determined the error, therefore it is absolutely random and without an apparent correlation.
function test() {
var tableHtml = 0;
var sheet = SpreadsheetApp.getActive().getSheetByName("2023");
var url = sheet.getRange("A27").getValue();
var html = UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"");
var tableHtml = html.match(/<table\s.*?id="pgl_basic"[\s\S]*?<\/table>/)[0];
var trs = [...tableHtml.matchAll(/<tr[\s\S\w]+?<\/tr>/g)];
var data = [];
for (var i=0;i<trs.length;i++){
var tds = [...trs[i][0].matchAll(/<(td|th)[\s\S\w]+?<\/(td|th)>/g)];
var prov = [];
for (var j=0;j<tds.length;j++){
donnee=tds[j][0].match(/(?<=\>).*(?=\<\/)/g)[0];
prov.push(stripTags(donnee));
}
data.push(prov);
}
return(data);
}
function stripTags(body) {
var regex = /(<([^>]+)>)/ig;
return body.replace(regex,"");
}
Initially the line:
var tableHtml = 0;
It didn't exist in the original code and I added it thinking it was a tableHtml variable "cache" issue but that didn't fix my problems. Using the code of the aforementioned topic, however, there is no problem or error but that code fetches all the tables included in the website and since they are not all the same, I don't need it but I need that specific table with that specific ID. I also tried to use a simple 2 second delay (via Utilities.sleep) thinking it could be a connection loading problem but this doesn't seem to be the case, also because I repeat that the original code (even with much larger data) works without a hitch. What could be the solution? Thanks.

handling new image file value is undefined in javascript

Working on a small guestbook posting site as part of a course however I've run into a little problem I cannot figure out.
Using a buttion to open file selection, to select an image and then process this file using the data url and create a key from the date.
However, during getting the file my data variable remains undefined all the way through and never receives the information it needs to show the image. and I'm unable to figure out the cause.
Below are the relevant parts.
function addPhotoClick() {
var inputElement = document.querySelector("#image input");
inputElement.click();
}
function processFile(event) {
debugger;
var data = event.target.result;
debugger;
var key = "diary" + Date.now();
debugger;
addImageEntry(key, data);
}
function initalize(){
var addPhotoButton = document.querySelector("#image button");
addPhotoButton.addEventListener("click", addPhotoClick);
}
Any help would be appreciated.
Try accessing file through image_field_id.files[0] instead of event. According to this, every browser which supports HTML5 should support this property.
Btw not sure if you need a button here, <input type="file"> should create one automatically.
And always add related HTML, please, it's not 100% clear how it looks like.

Content Controls getting lost when loading docx file via OOXML into another Word document

I have a Word Add In that loads a Word document into the current document. This is working just fine with the below code.
var myOOXMLRequest = new XMLHttpRequest();
var myXML;
myOOXMLRequest.open('GET', 'template.xml', false);
myOOXMLRequest.send();
if (myOOXMLRequest.status === 200) {
myXML = myOOXMLRequest.responseText;
}
Word.run(function (context) {
Office.context.document.setSelectedDataAsync(myXML, { coercionType: 'ooxml' });
});
Now I added some content controls to the Word document which I saved as template.xml (that serves as my template). When I now save the Word document containing the content controls as XML, and try to load it via the above code snippet, all works fine but the content contros are gone! I can't access them from Word, nor can I access them via Javascript like so:
var name = context.document.contentControls.getByTitle('myContentControl');
context.load(name);
return context.sync().then(function () {
var nameNew = name.items[0];
nameNew.insertText("Test", "Replace");
return context.sync().then(function () {
});
});
Is this a bug or is this just not possible? I also thought about putting some placeholders like ##myValue## into the Word template and then replacing those with values, but I'd rather do it with ContentControls if that is possible.
EDIT:
Here is the XML that I have created from my template: http://pastebin.com/NX0ZqLiM
I created the XML by just saving the Word document as XML and then loading as described above. Funny thing is, when I run the sample now I can see the content controls in Word. But when I try to access them via Javascript the ContentControl collection is always empty. I used a code sample from here https://dev.office.com/reference/add-ins/word/contentcontrol?product=word to try to access the content controls, but the collection of items is always empty.
Let me know if you need any more information.

loading images from json file with jquery

So I have a json file which now loads text and images individually pretty fine, this is just a simple example of what I did to test if it would work:
outputc+="<li>"
outputc+=this.name+" "+this.price+"</li>";
$('#featured').append(outputc);
$("<img/>").attr('src',this.images).appendTo('#featured');
Using the above code works perfectly however i need for both of these to be wrapped with a list, so I did some searching and I found this:
$(document).ready(function(){
//loading json file
var url = "shoppingItems.json";
$.getJSON(url,function(json){
$.each(json.shoppingItem,function()
{
var output ='<li><img src= "'+this.images+'" alt ="'+this.name+'"></li>';
});
$('.items').append(output);
});
});
The above jQuery doesn't bring back anything at all, there isn't anything wrong with my json file as it's been validated and the code works if I simply alert it. This is potentially something I must be doing wrong with my output script which I can't see.
My JSON file can be found here: Json file not loading or showing alerts
Since you declare it inside the callback function as var output, the output variable is local to that callback function and vanishes once the loop is completed. Even if that wasn't the case, the use of the = operator would mean you were overwriting the previous value with each iteraction.
Try this:
var output = ""; // initialize it outside the loop
$.each(json.shoppingItem,function()
{
output += '<li><img src= "'+this.images+'" alt ="'+this.name+'"></li>';
});
$('.items').append(output);
http://jsfiddle.net/mblase75/zB5fv/

PDF hostContainer callback

Following this SO solution here to notify clients of a click event in a PDF document, how is it possible to notify the client when the PDF gets submitted by the client using this.myPDF.submitForm("localhost/Handler.ashx?r=2) function?
The PDF File is created inside a user control then rendered into a HTML object:
string container = ("<object data='/myfile.pdf' type='application/pdf'></object>");
The JS file attached to the PDF is done like this:
var webClient = new WebClient();
string htmlContent = webClient.DownloadString(fileurl + "pdf_script.js");
PdfAction action = PdfAction.JavaScript(htmlContnent, pdfstamper.Writer);
pdfstamper.Writer.SetOpenAction(action);
And the content of the js file:
this.disclosed = true;
if (this.external && this.hostContainer) {
function onMessageFunc(stringArray) {
try {
this.myPDF.submitForm("http://localhost/Handler.ashx?EmpNo=12345" + "#FDF", false);
}
catch (e) {
}
}
function onErrorFunc(e) {
console.show();
console.println(e.toString());
}
try {
if (!this.hostContainer.messageHandler);
this.hostContainer.messageHandler = new Object();
this.hostContainer.messageHandler.myPDF = this;
this.hostContainer.messageHandler.onMessage = onMessageFunc;
this.hostContainer.messageHandler.onError = onErrorFunc;
this.hostContainer.messageHandler.onDisclose = function () { return true; };
}
catch (e) {
onErrorFunc(e);
}
}
When the submitForm call is made the PDF contents (form fields) get saved successfully and an alert is displayed in the PDF by doing this:
message = "%FDF-1.2
1 0 obj
<<
/FDF
<<
/Status("Success!")
>>
>>
endobj
trailer
<</Root 1 0 R>>
%%EOF");
return message;
What I'm trying to do is to get the PDF to callback the client after the form submit call sent from this client, a way to acknowledge the client that the form has been submitted, not in a form of an alert, but rather, a way to trigger a function in the host (the container, an iframe, object...etc).
The FDF response you used was unknown to me, so I've learned something new from your question. I've studied the AcroJS Reference and the FDF specification in the PDF Reference, and now I have a better understanding of what your code does. Thank you for that.
I assume that you already know how to trigger a JavaScript message in an HTML file using a JavaScript call from a PDF. See the createMessageHandler() in the JavaScript Communication between HTML and PDF article.
I interpret your question as: "How to I invoke this method after a successful submission of the data?"
If there's a solution to this question, it will involve JavaScript. I see that one can add JavaScript in an FDF file, but I'm not sure if that JavaScript can 'talk to' HTML. I'm not sure if you can call a JavaScript function in your initial PDF from the FDF response. If it's possible, you should add a JavaScript entry to your PDF similar to the /Status entry.
The value of this entry is a dictionary, something like:
<<
/Before (app.alert\("before!"\))
/After (app.alert\("after"\))
/Doc [/MyDocScript1, (myFunc1\(\)),
/MyDocScript2, (myFunc2\(\))
>>
In your case, I would remove the /Before and /Doc keys. I don't think you need them, I'd reduce the dictionary to:
<<
/After (talkToHtml\(\))
>>
Where talkToHtml() is a method already present in the PDF:
function talkToHtml() {
var names = new Array();
names[0] = "Success!";
try{
this.hostContainer.postMessage(names);
}
catch(e){
app.alert(e.message);
}
}
I don't know if this will work. I've never tried it myself. I'm basing my answer on the specs.
I don't know if you really need to use FDF. Have you tried adding JavaScript to your submitForm() method? Something like:
this.myPDF.submitForm({
cURL: "http://localhost/Handler.ashx?EmpNo=12345",
cSubmitAs: "FDF",
oJavaScript: {
Before: 'app.alert("before!")',
After: 'app.alert("after")',
Doc: ["MyDocScript1", "myFunc1()",
"MyDocScript2", "myFunc2()" ]
}
});
This will only work if you submit as FDF. I don't think there's a solution if you submit an HTML query string.
In case you're wondering what MyDocScript1 and MyDocScript2 are:
Doc defines an array defining additional JavaScript scripts to be
added to those defined in the JavaScript entry of the document’s name
dictionary. The array contains an even number of elements, organized
in pairs. The first element of each pair is a name and the second
is a text string or text stream defining the script corresponding
to that name. Each of the defined scripts is added to those already
defined in the name dictionary and then executed before the script
defined in the Before entry is executed. (ISO-32000-1 Table 245)
I'm not sure if all of this will work in practice. Please let me know either way.

Categories

Resources