JavaScript not functioning correctly in JSReport - javascript

trying to use document.getElementById() in jsreport using the scripts section on the left menu, but it reports back
Error occured - Error during rendering report: document is not defined
What gives? This is simple JavaScript to target a particular ID.

Scripts that are included as part of the report generation request rather than inline with the template do not contain document or any other objects generated by the browser.
If you are trying to use Javascript to modify the document, you are almost certainly doing something wrong. It's not meant to generate interactive content, so your template and data should already be fixed by the time you send the request. You can probably work around this with require.js, but why would you? If you are really generating a report, you can do everything ahead of time before you ever request output.

The problem is asynchronous related. the document.getElementById must come after the the element you want to target is built. So putting the script at the bottom of the page fixes the issue.

Related

Convert XML document to HTML and set <head>

I have an xml document loaded into the browser. I need to use it as a template to generate and display as an html page in its place, with all the work happening in JavaScript on the client.
I've got it mostly done:
The xml document loads a JavaScript file.
The JavaScript reads the document and generates the html document that I want to display.
The JavaScript replaces the document's innerHTML with the new html document.
The one thing that I'm missing is that I'd like to also supply the head of the new document.
I can create the head's content, of course. But, I cannot find any way to set it back into the browser's document. All my obvious attempts fail, hitting read-only elements of the document, or operations that are not supported on non-HTML documents.
Is there any way to do this, or am I barking up the wrong tree?
Alternative question: Even if this is really impossible, maybe it doesn't matter. Possibly I can use my JavaScript to accomplish everything that might be controlled by the head (e.g., viewport settings). After all, the JavaScript knows the full display environment and can make all needed decisions. Is this a sane approach, or will it lead to thousands of lines code to handle browser-specific or device-specific special cases?
Edited - added the following:
I think the real question is broader: The browser (at least Chrome and Chromium) seems to make a sharp distinction between pages loaded as .xml and pages loaded as .html. I'm trying to bend these rules: I load a page as .xml, but then I use JavaScript to change it into .html.
But, the browser still wants to view the page as .xml. This manifests in many ways: I can't add a <head>; I can't load CSS into the page; formatting tags are not interpreted as html; etc.
How can I convince the browser that my page is now bona fide html?

Blockly domToWorkspace reset node IDs

I'm working on an code editor using blockly, and my page currently has tabs for switching between Block View and Code View, kinda like some WYSIWYG editors. Now, Blockly already has plenty of stuff for going from blocks to code, and I've gotten 99% of the parts done so that I can go from code to blocks (it involves building up a bunch of block xml). My call to go from code view to block view looks like this:
var xml = Blockly.Xml.textToDom(self.xmlGenerated());
Blockly.mainWorkspace.clear();
Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
The problem is, no matter what id attributes I set in my xml nodes, blockly overrides them when I try to read the block xml later. It seems they constantly increment, even though I'm clearing the workspace. This causes a problem for my auto-save feature since that means each time I go from code to blocks my xml is changing, and therefore my code is changing (the generated code is a graph structure that also uses the id fields to identity each node in the graph).
So, my question is, does anyone know how to prevent Blockly from overriding the node id I send, or is there a way to "reset" the node ids?
I asked a very similar question in the Blockly Google group and Neil added a new data XML tag for storing persistent data. Maybe you can put your ID there? From reading the code seems like the id attribute was meant for internal use so it may be unreliable to reuse it.

using document.write in remotely loaded javascript to write out content - why a bad idea?

I'm not a full-time Javascript developer. We have a web app and one piece is to write out a small informational widget onto another domain. This literally is just a html table with some values written out into it. I have had to do this a couple of times over the past 8 years and I always end up doing it via a script that just document.write's out the table.
For example:
document.write('<table border="1"><tr><td>here is some content</td></tr></table>');
on theirdomain.com
<body>
....
<script src='http://ourdomain.com/arc/v1/api/inventory/1' type='text/javascript'></script>
.....
</body>
I always think this is a bit ugly but it works fine and we always have control over the content (or a trusted representative has control such as like your current inventory or something). So another project like this came up and I coded it up in like 5 minutes using document.write. Somebody else thinks this is just too ugly but I don't see what the problem is. Re the widget aspect, I have also done iframe and jsonp implementations but iframe tends not to play well with other site's css and jsonp tends to just be too much. Is there a some security element I'm missing? Or is what I'm doing ok? What would be the strongest argument against using this technique? Is there a best practice I don't get?
To be honest, I don't really see a problem. Yes, document.write is very old-school, but it is simple and universally supported; you can depend on it working the same in every browser.
For your application (writing out a HTML table with some data), I don't think a more complex solution is necessary if you're willing to assume a few small risks. Dealing with DOM mutation that works correctly across browsers is not an easy thing to get right if you're not using jQuery (et al).
The risks of document.write:
Your script must be loaded synchronously. This means a normal inline script tag (like you're already using). However, if someone gets clever and adds the async or defer attributes to your script tag (or does something fancy like appending a dynamically created script element to the head), your script will be loaded asynchronously.
This means that when your script eventually loads and calls write, the main document may have already finished loading and the document is "closed". Calling write on a closed document implicitly calls open, which completely clears the DOM – it's esentially the same as wiping the page clean and starting from scratch. You don't want that.
Because your script is loaded synchronously, you put third-party pages at the mercy of your server. If your server goes down or gets overloaded and responds slowly, every page that contain your script tag cannot finish loading until your server does respond or the browser times out the request.
The people who put your widget on their website will not be happy.
If you're confident in your uptime, then there's really no reason to change what you're doing.
The alternative is to load your script asynchronously and insert your table into the correct spot in the DOM. This means third parties would have to both insert a script snippet (either <script async src="..."> or use the dynamic script tag insertion trick. They would also need to carve out a special <div id="tablegoeshere"> for you to put your table into.
Using document.write() after loading the entire DOM do not allow you to access DOM any further.
See Why do I need to use document.write instead of DOM manipulation methods?.
You are in that case putting away a very powerfull functionnality of in web page...
Is there a some security element I'm missing?
The security risk is for them in that theirdomain.com trusting your domain's script code to not do anthing malicous. Your client script will run in the context of their domain and can do what it likes such as stealing cookies or embedding a key logger (not that you would do that of course). As long as they trust you, that is fine.

Javascript script/dom dependency?

When helping someone with a website that is rather large and have many includes I hit a bug and couldn't understand it. It was something like this
<script src=...></script>
<div ...
<script>
alert('myscript');
</script>
This page worked fine until I use that section of html and used jquery to ajax the content in. It broke the code but I don't understand why. I seen my alert. I can see the script is being access via the browser network log. I see some of the results of the first script tag but its broken.
Why does order matter? I thought as long as the dom is ready and the script is executed everything should be fine. But in this case being ajaxed in breaks it. I couldn't spend much time but it was curious to see something was dependent on timing.
--edit--
Also I notice if the script is already included on the page ajaxing in the content it will run fine
Does anyone have any idea why ajaxing in content breaks? When its not ajaxed in its fine.
Based on what you say, I give the following assessment :
40% likely -- it is about script load. Dependencies within the ajaxed script to other scripts, variables you define on the page, or even DOM content that is supposedly loaded could be not loaded at the time the script is ajaxed and executed.
Try changing the order of the script tag on the page, putting the loading of the script inside a document ready event handler, or delaying the script execution with setTimeout or defer="defer" -- or if you are really cool create a boot loader that ensures every script is loaded and executed in the exact order you specify : by chaining sets of dependency free simultaneous loads, to sequences of dependent loads.
Script1 <---- depends on --- (Script 2.1, Script 2.2, Script 2.3 )
<--- depends on --- Script3.
So load 1 first, then all the 2. scripts, then 3.
40% likely -- it is about security model. The website where you are ajaxing it from, Where is that? What is its relation to the domain the page is on? Are you testing this on localhost ?If so there are more restrictions. What about on an actual server? Is the Access-Control-Allow-Origin header set appropriately on the ajax response?
20% likely -- it is a circular dependency between the script and the DOM. Say some event handler on element X closes on a scope that references element X. Then there will be a reference to X inside a reference to X so they can't both be garbage collected, so X will persist, cause a memory leak, and possibly create an unusable reference which could be breaking your code.
--edit--
Based on your comment about .html(...) I think .html or .load to run scripts is too messy, and may not even work at all. See .load() doesn't load scripts for a nice way to load scripts with ajax. Or you could jQuery.getScript(...).
Also I seem to remember having issues even with loading html nodes from plain HTML using ajax. It just seems too messy to me. If you want to transfer structured information across ajax, use JSON, then present that information on your side with javascript and HTML. So, don't grab the whole data + presentation, just grab the data, then do your own presentation on your side. It's much neater.

Is there a way to validate the HTML of a page after AJAX operations are performed on it?

I'm writing a web app that inserts and modifies HTML elements via AJAX using JQuery. It works very nicely, but I want to be sure everything is ok under the bonnet. When I inspect the source of the page in IE or Chrome it shows me the original document markup, not what has changed since my AJAX calls.
I love using the WC3 validator to check my markup as it occasionally reminds me that I've forgotten to close a tag etc. How can I use this to check the markup of my page after the original source served from the server has been changed via Javascript?
Thank you.
Use developer tool in chrome to explore the DOM : it will show you all the HTML you've added in javascript.
You can now copy it and paste it in any validator you want.
Or instead of inserting code in JQuery, give it to the console, the browser will then not be able to close tags for you.
console.log(myHTML)
Both previous answers make good points about the fact the browser will 'fix' some of the html you insert into the DOM.
Back to your question, you could add the following to a bookmark in your browser. It will write out the contents of the DOM to a new window, copy and paste it into a validator.
javascript:window.open("").document.open("text/plain", "").write(document.documentElement.outerHTML);
If you're just concerned about well-formedness (missing closing tags and such), you probably just want to check the structure of the chunks AJAX is inserting. (Once it's part of the DOM, it's going to be well-formed... just not necessarily the structure you intended.) The simplest way to do that would probably be to attempt to parse it using an XML library. (one with an HTML mode that can be made strict, if you're not using XHTML)
Actual validation (Testing the "You can't put tag X inside tag Y" rules which browsers generally don't care too much about) is a lot trickier and, depending on how much effort you're willing to put into it, may not be worth the trouble. (Because, if you validate them in isolation, you'll get a lot of "This is just a fragment" false positives)
Whichever you decide to use, you need to grab the AJAX responses before the browser parses them if you want a reliable test result. (While they're still just a string of text rather than a DOM tree)

Categories