HTML Logo by World Wide Web Consortium (www.w3.org). Click to learn more about our commitment to accessibility and standards.

Moving forward with Composr

ocPortal has been relaunched as Composr CMS, which is now in beta. ocPortal 9 will be superseded by Composr 10.

Head over to compo.sr for our new site, and to our migration roadmap. Existing ocPortal member accounts have been mirrored.


Change to ocPortal Javascript - Comments

Login / Search

 [ Join | More ]
 

Change to ocPortal Javascript

Posted 08 April 2011, 3:40 PM
In the next patch release for ocPortal 6 there's going to be some slight Javascript changes.

Situation X

It is worth noting that ocPortal's setInnerHTML does run Javascript, whilst setting the normal Javascript .innerHTML property (the non-standard one that Microsoft invented, but all browsers support) does not. There is no change, ocPortal has done this for some time and it is very useful, so…

Read more


Looks useful

Avatar
I'm certainly guilty of not using onload events, but I'm not quite as bad as the example in "situation 2"; my DOM usage is usually within functions that likely won't be fired until well after the page has loaded.

The first change is certainly useful though, since now Comcode can be used reliably for content brought in via AJAX (eg. via the really easy-to-use snippets hooks). I will point out a slightly non-obvious issue though; even though the Javascript may run, it may depend on scripts that haven't been loaded yet. To solve this, put the following near the start of the template used for your AJAX replies {$JS_TEMPCODE}. That will ensure that anything added to the "required javascript" list will get sent along with the Comcode that depends on it :)

Another issue, maybe a little more obscure; if you're sending rendered Comcode to a browser via AJAX, you'll encounter annoyances with CDATA tags since ocPortal wraps (almost) all Javascript in them, but, like /*comments*/,  they can't be nested. You can encode and decode the rendered Comcode to get around this, for example with Base64 (since that can be easily encoded by PHP and decoded by the browser) :)

Avatar

ChrisW said

… you'll encounter annoyances with CDATA tags since ocPortal wraps (almost) all Javascript in them, but, like /*comments*/,  they can't be nested …

Got all of what Chris said (needed to be read a few times), and got most of what ChrisW has said, although it is way above my pay grade.

However, a little clarification please, ChrisW: did you mean to say …
… you'll encounter annoyances with CDATA tags since ocPortal wraps (almost) all Javascript in them, but, like unlike /*comments*/,  they can't be nested …
… or does your original phraseology stand? If so, I am totally confused!

 :'(

Avatar
even though the Javascript may run, it may depend on scripts that haven't been loaded yet

Ah yes, this is another reason to rely on 'load' for your code, forgot about that one. However this said, no inline scripts run before scripts loaded in the <head> have loaded.


I've made another change. Asking for 'load' will now use 'DOMContentLoaded' for browsers that support it (which includes IE9). This makes pages render much faster as they don't wait for all images to load. If you really want 'load' you can ask for 'real_load' which will disable this new behaviour as well as the late-loading-support behaviour.

Avatar
@Fletch: My original phraseology stands. The issue is that putting something between <![CDATA[ and ]]> tells the XML reader (eg. the browser) to essentially ignore everything it finds until it reaches ]]>. This allows other languages, like Javascript, to be embedded inside XHTML without conflicts. The problem is that, since the regular XML rules are being ignored, this includes the rules to do with CDATA tags, so a CDATA tag nested inside another one will simply be skipped over, but its end tag will be spotted and will close the outer CDATA tag.

For example, it's easy to write an ocPortal template that says something like <![[CDATA {PARAMETER} ]]> and assume that it will force the contents of PARAMETER to be ignored by the XML reader, but that's not true. What actually happens is that everything in PARAMETER will be ignored up to the end of PARAMETER's first CDATA tag. So it will break if PARAMETER contains any CDATA tags of its own.

CDATA is used a lot when writing AJAX code, since we may want to deliver some arbitrary 'payload' without having to care if it fits into the XML of our reply, which can hit this problem.

Let's say we had an AJAX-enabled comment box, so that new comments would be retrieved from the server without needing to refresh the page. The server can use a template that looks like this <xml><comment>{COMMENT_BODY}</comment></xml> and the Javascript looks for whatever's inside <comment>. However, that may break the XML rules for some reason, for example if COMMENT_BODY is a table cell (which can only exist in a table row), or a list item (which can only exist in a list). The simple fix is to use this instead <xml><comment><![CDATA[{COMMENT_BODY}]]></comment></xml> which means that COMMENT_BODY won't be checked for validity. We then run into the nested CDATA problem though, since the comment might contain some CDATA of its own (especially around Javascript), for example if it contains the pulse tag.

The solution is to run COMMENT_BODY through an encoding system like Base64. This will guarantee that our reply won't directly contain any nested CDATA tags, but the full content of the payload, CDATA included, will be intact after it's decoded by Javascript.

The same issue arises with HTML comments, which are between <!-- and -->, which is why Tempcode contains its own comment syntax. For example a page template might contain a block, but we wish to comment it out for the moment. If we put <!-- {$BLOCK,block=my_block} -->, and the block's own template contains some HTML comments, then we reach the same issue that the end of the block's comment will close the page's comment. The same happens in PHP if we tried to put /* I am a comment /* I am also a comment */ text here is actually outside a comment */, although we don't tend to rewrite PHP automatically, except in a few rare places, so we can spot those errors immediately when we open the file for editing.

Avatar
Thanks ChrisW, for that detailed explanation. Amazingly I am able to understand this particular issue, but sadly (it's an age thing - came to this platform too late in life) I don't grasp the fundamentals of the bigger picture.

That's not your fault; it is a simple fact of life. I will continue to 'delve' into waters that are too deep for me, but it certainly keeps the old grey cells ticking over. And it stops me from degenerating into the vegetable that one expects somebody of my age and intellect, to have become by now!

Keeps me off the streets and out of the pubs as well …

 :lol:

1 guests and 0 members have just viewed this: None
Control functions:

Quick reply   Contract

Your name:
Your message: