doc-write.js
NAME
doc-write.js – A library providing a surrogate function and plug-in replacement for document.write() under XHTML
to the topSYNOPSIS
<script type="application/javascript" src="https://public.robidu-static.de/devel/js/doc-write.js" />
<script type="application/javascript">
/* <![CDATA[ */
document.open();
document.write(string[,string[...]]);
document.writeln(string[,string[...]]);
document.close();
/* ]]> */
</script>
DESCRIPTION
This library provides four surrogate functions for manipulating XHTML documents
by directly writing to it. Since the DOM does not provide these methods (or
rather causes an error to be written to the browser console) when XHTML is
parsed, there is no way of directly writing anything to these documents. The
reason behind this: Since arbitrary strings could be written to the document,
this could easily invalidate the entire XHTML document. However, this is highly
undesirable under certain circumstances so a workaround needed to be found.
This library provides the exact four functions that can be used to manipulate
ordinary HTML documents so that dynamically adding content can easily be
facilitated under XHTML as well.
This library may also be included in normal HTML documents to replace the
built-in functions with these. However, this is not recommended and may not
work as expected, but on the plus side you get a bunch of sanity checks on the
data that you pass to document.write().
document.open();
Like the real function this one opens a document for writing data to it. Any
content currently present in the document is cleared.
However, since this function is only emulating opening the document, this
library handles everything internally and sets a flag to indicate that the
document may be written to.
This method needs not be issued when the document is still loading since it means that it is still open.
to the topdocument.write();
This works similar to the real function in that it takes one or more arguments
and writes them out to the document. However, whereas the built-in function
adds the parameters to the document's source code, this function needs to take
a different approach to adding the new content to the document.
If the document hasn't been opened prior to writing, document.open() is invoked
implicitly, except when the library has been set to Strict Operation. In that
case writing to a document that hasn't been opened throws an exception.
This function takes one or more strings to be converted to a DOM subtree.
to the topdocument.writeln();
Works similar to document.write(), except that a line break is appended to the parameters. This is a wrapper function for document.write() which appends the line breaks and passes the parameters to the aforementioned function.
This function takes one or more strings to be converted to a DOM subtree.
to the topdocument.close();
The document is closed. This clears the internal flag to indicate that no more data may be written to the document.
to the topDEVELOPMENT
After looking for a solution to add document.write() to the DOM to return some capabilities to the browser that have been lost due to the restrictions of XHTML, I had found some solutions on the Internet that turned out to be highly unsatisfactory. They may have been small and fast, but they came along without virtually any sanity checks so that arbitrary – and therefore even outright nonsensical – strings could be passed to it.
It has been these shortcomings of the original concept that led to this library
being created: A plug-in replacement that also validates the input that is
passed to it.
Its speed may not match that of the original concept, but you can be sure that
the outcome is valid XHTML when calling this library is successful.
THE PARSER
Since this library cannot just write out the parameters that have been passed to document.write(), a DOM subtree must be constructed from the parameters prior to inserting the contents into the document's DOM tree. To ensure a valid result a wide range of sanity checks must be applied. Should there be an error in the XHTML, an exception is thrown and an error message is written to the console.
Like the built-in function this one may be invoked when the document is still being loaded to include additional content. However, adding content doesn't have an immediate effect, but any actions are deferred until the entire DOM tree has been constructed.
You also need to make sure that anything that is passed to this function either resides in a block element of any type or, if not, creates one to house the other content found in the string. If no containing block element is found in the string the parser backtracks all the way up to the body node to find a containing block element. If none is found, an exception is thrown.
to the topLIMITATIONS
Although this library tries its best to properly emulate the built-in function,
it cannot map all of its traits. Since you cannot just pass arbitrary XHTML
code to document.write() and expect this function to work,
you are required to take certain possibilities for disaster into account.
Especially passing illegal XHTML to this function is going to cause failure.
However, since the parser throws an exception if it encounters an error, you
can trap it as long as you haven't instructed the library to defer parsing of
the XHTML.
If you are experiencing trouble, have a look especially at the exceptions that
this library is throwing. If you are getting syntax or context errors, you are
most likely attempting to produce tag soup so something must be wrong with your
markup.
After the document has completed loading a call to document.open(); doesn't clear the entire document, because that would also clear out this library from the DOM. The body section of the document is cleared instead and can be filled with new content.
Another limit is that you cannot just pass some plaintext followed by a closing tag, then follow it up with an opening tag and more plaintext in order to split a block in half. Checks on the structural integrity of the XHTML are strict in this regard, and attempting anything like that inevitably results in a failure.
to the topCONTROLS
The mode of operation of this library can be controlled with some metadata tags
in the head section of the document that pass particular flags to it.
If multiple values can be specified, you can provide a comma-separated list.
It depends on the variant of this library that you are using which controls are
present. The network control is, for example, only available in the
network-capable variant which doesn't bring along any initial data, because
that needs to be downloaded.
- docwrite-flags
- This collection of flags controls the general mode of operation and
provides a variety of flags. These are the following:
- warn2err
- Turns some warnings into errors, i. e. causes parsing of the XHTML to fail under certain conditions that would otherwise be recoverable.
- async
- Causes the parsing process to be detached from the normal flow of control. This can increase responsiveness of the interface, because the process of parsing the XHTML is running outside of the context of the caller, but the presence of any objects to be added to the DOM tree cannot be guaranteed to exist after the call has returned.
- verbose
- Produces additional output that includes execution statistics and additional information on this library's performance. This flag may not be supported in variants of this library that are trimmed for size.
- strict-op
- Forces this library to strict operation. In this mode explicitly opening the document is required before writing anything to it, as is closing it afterwards. Trying to write to a document that hasn't been opened throws an exception.
- relaxed
- Relax the checks on the data passed to
document.write(). This can be used to drop the strict
checks that are normally applied to XHTML when this library is used with
ordinary HTML documents. However, tag soup still won't be accepted!
Beware: If you are using this library in conjunction with XHTML documents, strict checks are applied even though this flag may be set!
- docwrite-debug
- This flag controls whether or not the library should output additional debugging information to the browser console. It may not be present in every variant of this library (especially the production versions don't have debug capabilities) so if you have any issues and need debug messages, you need to switch to a variant that supports debug mode.
- docwrite-net
- This setting controls how this library reacts to network failures. If you
are using a library that needs the network to load its data, you can set some
parameters that modify the behavior of its requests.
- retry=n
- Sets the number of retries to n. The library
attempts to fetch the data this number of times before giving up. Values
greater than 10 are capped at 10, and setting this to a value of 0 or below
results in an immediate faiure when the resources cannot be retrieved.
The default is 3 retries. - timeout=n
- Sets the request timeout to n seconds. The value
must be between 5 and 30 seconds.
The default is 10 seconds. - backoff=n
- Sets the grace period between requests that have timed out to
n seconds. The value must be between 0 and 60
seconds.
Normally it is sufficient to repeat such a request immediately after it has timed out, but on some occasions it could be better to impose a delay before repeating the request.
The default is 0 seconds (no backoff period). - local={on|off}
- Controls whether or not the library may use local storage to save anything
that it has downloaded. Any downloaded data is put into local storage so that
subsequent invocations don't have to download it again. Regular checks are
nonetheless performed to see whether there's updated data available and load it
when necessary.
This setting can be used to turn local storage on or off. However, turning local storage off doesn't prevent the library from using any data still present in storage, but it merely turns off update cycles.
The default is on.
EXPERIMENTAL FEATURES
None so far.
to the topCAVEATS
Because of this library's capability of deferring the parsing of any argument
strings, caution must be applied when you need to access any content that you
have dynamically written to the document!
Especially when the document is still loading, you must not rely on any new
content being available during this stage, because it's not! Although a call to
document.write() seems to have been successful, processing
actually starts when the DOMContentLoaded event is fired, that is, the document
has completed loading and its DOM tree has been constructed. Before that all
data is merely queued for processing.
The need for actually parsing any arguments passed to this document.write() introduces additional opportunities for problems. When anything illegal is detected, processing of that particular parser node is aborted and any content that should have been introduced into the DOM tree is discarded. To avoid problems, you are required to check whether or not a particular invocation of document.write() has been successful and the new content is actually available.
to the topBUGS
If you find anything to be amiss with this, please feel free to send a bug
report to olaf.martens@robidu.de – but before you sumbit anything, please
consult the sections THE PARSER,
LIMITATIONS,
EXPERIMENTAL FEATURES, and
CAVEATS. Many issues that seem like a malfunction are
simply founded on the limitations of this interface whose capabilities are a
subset of those from the original document.write().
Also, before you report, make sure to check the browser console for error
messages. If anything has gone wrong, you can find the answer there.
However, if you have any ideas on improving this library, please feel free to join the effort!
to the topAUTHORS
Concept and initial version: Olaf Martens <olaf.martens@robidu.de>
to the top