[templates spec] @oncreate

5 views
Skip to first unread message

Lev Epshteyn

unread,
Mar 31, 2009, 6:03:49 PM3/31/09
to opensocial-an...@googlegroups.com, Scott Seely, Christopher Cole, Adam Winer, Evan Gilbert
http://codereview.appspot.com/33041

This, I believe is the last bit - something was discussed on the list with no objections in the past, but somehow never made it into spec proper.

This may seem pretty client-oriented, but can be implemented with server-side rendering by injecting inline scripts.

For example,

<div oncreate="foo()">bar</div>

can be rendered as

<div>bar</div><script id="__oncreate23">
  new Function('foo()").apply(document.getElementById("__oncreate23").previousSibling)
</script>


Scott Seely

unread,
Mar 31, 2009, 6:39:40 PM3/31/09
to Lev Epshteyn, opensocial-an...@googlegroups.com, Christopher Cole, Adam Winer, Evan Gilbert

-1

 

We have gadgets.util.registerOnLoadHandler that handles this scenario just fine. One can also go for the more primitive window.onload.

Lev Epshteyn

unread,
Mar 31, 2009, 6:57:06 PM3/31/09
to Scott Seely, opensocial-an...@googlegroups.com, Christopher Cole, Adam Winer, Evan Gilbert
Just to be clear, this proposal is not for a generic onload handler, but for fine-grained DOM-to-JS registration. The example in the patch demonstrates something that cannot be done with an onload handler without walking the DOM.

Personally I am OK if this is not in v0.9, just want to make sure everyone understands the point of the proposal.

Adam Winer

unread,
Mar 31, 2009, 7:10:05 PM3/31/09
to opensocial-an...@googlegroups.com, Lev Epshteyn, Christopher Cole, Adam Winer, Evan Gilbert
A better example is:

<div repeat="${...}" oncreate="decorateAsButton(this)">bar</div>

<script>
function decorateAsButton(element) { .... }
</script>

This is very difficult without @oncreate; registerOnLoadHandler() is
not an easy replacement.

That said, I'm +0 on adding it in 0.9, and would be fine with it as an
extension to explore if it's a valuable feature.

-- Adam

Scott Seely

unread,
Mar 31, 2009, 8:20:08 PM3/31/09
to opensocial-an...@googlegroups.com, Lev Epshteyn, Christopher Cole, Adam Winer, Evan Gilbert
Hard-- the common mechanism here is something like:

<div repeat="${...}" class="mySpecialButton">bar</div>


If "mySpecialButton" needs to have extra code attached to it, one uses a CSS selector
And then use a style based selector (JQuery) to do:

$(".mySpecialButton")/* now-- operate on all instances doing whatever */

Alternatively, sticking to just OSML:

<os:Repeat expression="${...}">
<div>bar</div>
<script id="_oncreate${Context.Index}">
function('foo()').apply(document.getElementById("_oncreate${Context.Index}").previousSibling);
</script>
</os:Repeat>

Evan Gilbert

unread,
Apr 1, 2009, 12:58:52 PM4/1/09
to Adam Winer, Scott Seely, opensocial-an...@googlegroups.com, Lev Epshteyn, Christopher Cole
Few reasons why I think @oncreate is much better than these alternatives (more on each below):
1. @oncreate largely allows us to avoid inline <script> blocks in templates, and inline <script> blocks have a lot of problems
2. The optimal time to decorate HTML DOM elements (to avoid flicker, etc) is right after they are inserted into the DOM. @oncreate can do this, don't believe the other methods can.
3. Both the JQuery mechanism and the ID based mechanism would require OpenSocial extensions to work. JQuery would require a registration mechanism for class name -> JS handller, ID based requires a unique ID generation mechanism.
4. Implementation is nearly trivial in server side processing (and already works on client side)

I'm OK if @oncreate is as an extension that is only supported in the JS and some server-side implementations - but think it may be worth putting in the spec now becasue of these issues.

In more detail...

@oncreate largely allows us to avoid inline <script> blocks in templates
- We want to discourage developers from <script> tags inside OSML templates (at one point this was going to be prohibited, but didn't make it into the spec). Developers should use <Javascript> in standalone template libs, or separate <script type="text/javascript"> block when embedded in HTML pages.
- <script> won't work in iline HTML currently as the closing </script> will close the <script type="text/os-template"> tag.
- You don't want to have replacement variables in JS functions - this is prone to error (function foo() { return '${bar}'}
- You don't want to evaluate JS functions once per iteration. Developers will usually include the onXXX functions inline if included in the script - i.e. <a onclick="doThis()"></a><script type="text/javascript">function doThis() {...}</script>. This is bad, as we create the "doThis()" function once per time we create the <a> tag, instead of once overall. There are solutions to this, but they are complicated and it's easier to just declare functions externally to the template blocks.
- @oncreate was the only tag we needed to avoid these problems - it allowed executing a JS call once per time an element is created, and this was the only real need for inline <script> elements that couldn't be satisfied externally

The optimal time to decorate HTML DOM elements is right after they are inserted into the DOM
- Decorators (i.e. makePrettyButton(htmlElement) need to be called immediately after DOM insertion, otherwise the user may see the undecorated element for a period of time. onLoad() handlers aren't soon enough
- Also, we don't have a mechanism to do this when rendering after initial page load. We'd have to add a new JS function "callSoonButNotImmediately(callback)" which would register an onload handler if the page isn't loaded, otherwise call setTimeout(0). Note that setTimeout (0) still creates flicker, as this allows the browser to finish everything else it needs to do before rendering.

Other mechanisms require extending OpenSocial anyway:
- If you want to use IDs in DOM elements, you need a way to create a unique ID for the DOM elements, as template blocks are reused. We had this at one point with {$Context.UniqueId}, but it's currently not in the spec and so there is no way to generate a unique element ID.
- For the CSS selector mechanism, you need the callSoonButNotImmediately() function, and you also need to ensure the DOM is walked only once. So code would look like
<a class="funlink">..</a><script type="text/javscript">gadgets.callSoonButNotImmediately(function() { registerClassDecorator('funlink', funlinkDecorator);})</script>. This requires an extension and is also nearly incomprehensible.

Server side implementation is easy:

  <el oncreate="FUNCTION">...</el>
Changes to:
(note: need to generate an element ID if the element doesn't have one already. This doesn't need to be exposed to developers)

  <el id="ID">...</el>
  <script type="text/javascript">
    var fn = function() {
      FUNCTION
    }
    fn.apply(document.getElementById('ID');
  </script>

Evan

On Tue, Mar 31, 2009 at 5:23 PM, Adam Winer <awi...@google.com> wrote:
On Tue, Mar 31, 2009 at 5:20 PM, Scott Seely <sSe...@myspace.com> wrote:
> Hard-- the common mechanism here is something like:
>
> <div repeat="${...}" class="mySpecialButton">bar</div>
>
>
> If "mySpecialButton" needs to have extra code attached to it, one uses a CSS selector
> And then use a style based selector (JQuery) to do:
>
> $(".mySpecialButton")/* now-- operate on all instances doing whatever */
>
> Alternatively, sticking to just OSML:
>
> <os:Repeat expression="${...}">
>        <div>bar</div>
>        <script id="_oncreate${Context.Index}">
>        function('foo()').apply(document.getElementById("_oncreate${Context.Index}").previousSibling);
>       </script>
> </os:Repeat>

Works for me (especially the JQuery approach);  I think I'm swayed to
-1 on @oncreate for 0.9.

-- Adam

Lev Epshteyn

unread,
Apr 1, 2009, 1:29:50 PM4/1/09
to Evan Gilbert, Adam Winer, Scott Seely, opensocial-an...@googlegroups.com, Christopher Cole
I generally agree with Evan - I think this attribute is particularly useful for creating complex client side UIs where you have Javascript data structures linked to DOM ui elements.

For example if I have a javascript Calendar widget with a constructor that takes a div, I could provide a custom tag for it:

<script type="text/os-template" tag="my:Calendar">
  <div style="width: 200px; height: 150px" oncreate="my.Calendar.newInstance(this)">
    Loading calendar...
  </div>
</script>

The newInstance(div) call would create inner DOM, attach proper event handlers etc. There is a lot of power here, and it's a much more elegant way to do it than to go searching for divs with className == "calendar".

So while it's not critical functionality, it is very useful - if this does not make it to spec, it will probably appear in Shindig as an extension.

BTW, Evan, my proposal for server side impl did a better job handling the edge case where for some reason the developer has decorated an element with @oncreate with a non-unique @id :)

Scott Seely

unread,
Apr 1, 2009, 1:30:29 PM4/1/09
to Evan Gilbert, Adam Winer, opensocial-an...@googlegroups.com, Lev Epshteyn, Christopher Cole

We will be starting on v.NEXT proposals by end of month. At this late stage, I would prefer to spend some time getting feedback from developers on their experience with OSML before going further. Do we lose anything by noting the proposal and having a more informed discussion post 0.9?

 

If not, I have comments inline below

 

From: Evan Gilbert [mailto:uid...@google.com]
Sent: Wednesday, April 01, 2009 9:59 AM
To: Adam Winer
Cc: Scott Seely; opensocial-an...@googlegroups.com; Lev Epshteyn; Christopher Cole
Subject: Re: [opensocial-and-gadgets-spec] Re: [templates spec] @oncreate

 

Few reasons why I think @oncreate is much better than these alternatives (more on each below):
1. @oncreate largely allows us to avoid inline <script> blocks in templates, and inline <script> blocks have a lot of problems
2. The optimal time to decorate HTML DOM elements (to avoid flicker, etc) is right after they are inserted into the DOM. @oncreate can do this, don't believe the other methods can.
3. Both the JQuery mechanism and the ID based mechanism would require OpenSocial extensions to work. JQuery would require a registration mechanism for class name -> JS handller, ID based requires a unique ID generation mechanism.
4. Implementation is nearly trivial in server side processing (and already works on client side)

I'm OK if @oncreate is as an extension that is only supported in the JS and some server-side implementations - but think it may be worth putting in the spec now becasue of these issues.

In more detail...

@oncreate largely allows us to avoid inline <script> blocks in templates
- We want to discourage developers from <script> tags inside OSML templates (at one point this was going to be prohibited, but didn't make it into the spec). Developers should use <Javascript> in standalone template libs, or separate <script type="text/javascript"> block when embedded in HTML pages.

[[sseely]] The proposal indicates that the generated DOM would have this exact issue, but the inline script blocks would be gen’d instead of authored by the dev. I see no difference here since the same end result occurs.


- <script> won't work in iline HTML currently as the closing </script> will close the <script type="text/os-template"> tag.

[[sseely]] Incorrect. This won’t work in quirks mode HTML processing. Choosing to do this while requiring XHTML avoids the issue. According to http://opensocial-resources.googlecode.com/svn/spec/draft/OpenSocial-Templating.xml#rfc.section.4, any markup within a <script type=”text/os-template”> requires well formed XML. If you fail because of an early close, your implementation has a bug.


- You don't want to have replacement variables in JS functions - this is prone to error (function foo() { return '${bar}'}

[[sseely]] I will grant that the OSML version isn’t preferred—it was offered solely for illustrative purposes. JQuery, Prototype, Moo, Dojo, or similar is preferred.


- You don't want to evaluate JS functions once per iteration. Developers will usually include the onXXX functions inline if included in the script - i.e. <a onclick="doThis()"></a><script type="text/javascript">function doThis() {...}</script>. This is bad, as we create the "doThis()" function once per time we create the <a> tag, instead of once overall. There are solutions to this, but they are complicated and it's easier to just declare functions externally to the template blocks.

[[sseely]] I know—but Lev suggested the particular inline representation of how to render the @oncreate. I simply followed his lead to show an equivalent implementation written in draft form OSML. This was done to illustrate that if that final representation was desired, it could be obtained simply without a change to the spec.


- @oncreate was the only tag we needed to avoid these problems - it allowed executing a JS call once per time an element is created, and this was the only real need for inline <script> elements that couldn't be satisfied externally

[[sseely]] This problem already exists outside of OpenSocial and libraries exist to solve this problem (and are consistently improved upon to run faster and faster).



The optimal time to decorate HTML DOM elements is right after they are inserted into the DOM
- Decorators (i.e. makePrettyButton(htmlElement) need to be called immediately after DOM insertion, otherwise the user may see the undecorated element for a period of time. onLoad() handlers aren't soon enough

[[sseely]] CSS handles visual cues. Onclick and the like can be added in window.onload (and it’s equivalents) with no visual distraction. We have a solution to the problem in the HTML/CSS world.


- Also, we don't have a mechanism to do this when rendering after initial page load. We'd have to add a new JS function "callSoonButNotImmediately(callback)" which would register an onload handler if the page isn't loaded, otherwise call setTimeout(0). Note that setTimeout (0) still creates flicker, as this allows the browser to finish everything else it needs to do before rendering.

[[sseely]] Again—visual elements can already be handled using well-known mechanisms. Typical usage is to draw everything, then do a blanket attachment of event handlers after the fact.



Other mechanisms require extending OpenSocial anyway:
- If you want to use IDs in DOM elements, you need a way to create a unique ID for the DOM elements, as template blocks are reused. We had this at one point with {$Context.UniqueId}, but it's currently not in the spec and so there is no way to generate a unique element ID.

[[sseely]] Are you proposing the wrong thing then? It seems so. This is why we shouldn’t rush to add new features when we will have a chance to do so again in May.


- For the CSS selector mechanism, you need the callSoonButNotImmediately() function, and you also need to ensure the DOM is walked only once. So code would look like
<a class="funlink">..</a><script type="text/javscript">gadgets.callSoonButNotImmediately(function() { registerClassDecorator('funlink', funlinkDecorator);})</script>. This requires an extension and is also nearly incomprehensible.

Server side implementation is easy:

  <el oncreate="FUNCTION">...</el>
Changes to:
(note: need to generate an element ID if the element doesn't have one already. This doesn't need to be exposed to developers)

  <el id="ID">...</el>
  <script type="text/javascript">
    var fn = function() {
      FUNCTION
    }
    fn.apply(document.getElementById('ID');
  </script>


[[sseely]] Again, I’d prefer to allow developers to attack these problems using tools they already know and understand. I see no compelling reason to push to figure this out for 0.9.

Scott Seely

unread,
Apr 1, 2009, 1:34:20 PM4/1/09
to Lev Epshteyn, Evan Gilbert, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole

The time to bring this up was when it was being considered for inclusion in Shindig. Please be more proactive in the future so that we can have fruitful discussions without the time pressure of getting the spec done.

 

I look forward to seeing a more formal proposal in v.Next.

Christopher Cole

unread,
Apr 1, 2009, 1:35:07 PM4/1/09
to Scott Seely, Evan Gilbert, Adam Winer, opensocial-an...@googlegroups.com, Lev Epshteyn

I am a pretty strong -1 on this proposal.  While a server-side implementation may be easy, this is straying into extending the html DOM model its self, which I view as well beyond scope of what's appropriate for OpenSocial and OSML. 

 

If a node decorator is the only use case for adding this, it could be much more appropriately handled via css class definitions and adding them to the nodes as they are emitted.  I would be interested to see shindig make this extension and bring associated developer feedback to the kickoff of v.Next.

--

clc

 

 

From: Scott Seely

Sent: Wednesday, April 01, 2009 10:30 AM

Evan Gilbert

unread,
Apr 1, 2009, 1:41:59 PM4/1/09
to Scott Seely, Lev Epshteyn, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole
I'm happy using an extension until v.Next.
(note: from a process perspective this is a real issue from prototyping that we discovered, but sounds like there are enough concerns that we won't resolve it quickly).

Should we use @oncreate for the extension or @xoncreate (or something different)? We currently don't have a clear guideline on how to name extension features.

Evan

Scott Seely

unread,
Apr 1, 2009, 1:44:08 PM4/1/09
to Lev Epshteyn, Evan Gilbert, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole

My understanding is that Shindig was supposed to represent a conforming implementation of OpenSocial. Does Shindig call out bits that are extensions in the documentation?

 

I’m primarily interested in looking at this to see if the developers on Shindig have had other interesting ideas that need to be considered for v.Next as either extension specs or for incorporation into the mainline spec.

 

From: Lev Epshteyn [mailto:le...@google.com]

Sent: Wednesday, April 01, 2009 10:30 AM
To: Evan Gilbert
Cc: Adam Winer; Scott Seely; opensocial-an...@googlegroups.com; Christopher Cole

Evan Gilbert

unread,
Apr 1, 2009, 2:04:03 PM4/1/09
to Scott Seely, Lev Epshteyn, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole
On Wed, Apr 1, 2009 at 10:44 AM, Scott Seely <sSe...@myspace.com> wrote:

My understanding is that Shindig was supposed to represent a conforming implementation of OpenSocial. Does Shindig call out bits that are extensions in the documentation?

 

I’m primarily interested in looking at this to see if the developers on Shindig have had other interesting ideas that need to be considered for v.Next as either extension specs or for incorporation into the mainline spec.



I don't think there are many extensions currently (although http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#features has a good list of features that most non-Shindig container probably don't even realize is part of the official spec)

Moving forward, we'd like to have a standard way to add extensions and have them clearly marked as such - for example, Google is creating a number of OSML tags for server-side rendering on Orkut (flash support, etc), and we want to make them generally available for conatiners to use.

Scott Seely

unread,
Apr 1, 2009, 2:15:24 PM4/1/09
to Evan Gilbert, Lev Epshteyn, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole

For marking OpenSocial extension attributes, I think something like osx-[attribute] would be a sensible way to go. If Apple considers OSX to be a trademark, then xos- is also sensible.

 

Regarding the tag extensions—this idea has been kicked around our office too. It seems that most tags that can be implemented as template libraries should be implemented that way—no need to bother the spec process with every tag. I would be interested in a side discussion about things you are finding with Flash support and why you are or are not developing and processing Template libraries for the new tags.

Lev Epshteyn

unread,
Apr 1, 2009, 2:49:55 PM4/1/09
to Scott Seely, Evan Gilbert, Adam Winer, opensocial-an...@googlegroups.com, Christopher Cole
So I guess we have consensus to kill this as a spec change for the time being.
Reply all
Reply to author
Forward
0 new messages