Titanium JIRA Archive
Alloy (ALOY)

[ALOY-33] CSS runtime parsing needs to be revised

GitHub Issuen/a
TypeImprovement
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2012-07-19T11:52:04.000+0000
Affected Version/s2012 Sprint 14
Fix Version/s2012 Sprint 14
ComponentsRuntime, XML
Labelsn/a
ReporterTony Lukasavage
AssigneeTony Lukasavage
Created2012-05-08T15:08:09.000+0000
Updated2014-06-22T13:21:16.000+0000

Description

Currently at runtime, CSS is parsed by reading strings, parsing them, then applying the appropriate titanium properties based on the style. This runtime string parsing will inevitably create a performance issue as the complexity of an app grows. We need to rethink how we are going to handle CSS at runtime in a way that performs more efficiently. A likely alternative would be to create JSON structures for the CSS at translation time that can then be accessed by the Titanium app at runtime. That where there would only be runtime css parsing if a user manually modifies the CSS in code.

Comments

  1. Tony Lukasavage 2012-05-22

    Lazy loading of the components complicates application of CSS. If CSS selectors are applied in a different order than the DOM is created, you have the potential of lazy loaded components getting created before their parents. app.css
       #header {
           /* various header properties */
       }
       
    app.html
       <div id="mainWindow>
           <div id="header"></div>
       </div>
       
    Due to the way the $Ti selector code is structured, and the nature of the lazy loading of Ti objects from DOM objects, if the CSS rule for #header is processed before #mainWindow is accessed, there will be an exception. This is because the $Ti selector code will assume then that the lazy loaded #header element can be added to its parent #mainWindow, but #mainWindow doesn't exist yet.
  2. Russell McMahon 2012-05-22

    Can we make sure a parent is created before a child? Maybe walk the dom tree to the root () and make sure a complete view tree is available before the child is added.
  3. Russell McMahon 2012-05-22

    I had thought that there was code already doing that, but if you are seeing a crash then you are correct we need to revisit.
  4. Tony Lukasavage 2012-05-22

    walking up the tree is likely what we will have to do. We could also have a parameter for the $Ti selector that indicates we don't want to create Ti objects as we encounter them, but that doesn't really solve the root problem. Perhaps the last thing that happens in the app_dom.js, after the DOM is constructed, is accessing the root Titanium node. This would create all the DOM elements for the current DOM for the current view. This leads me to a more important question. Should lazy loading even be necessary inside a view? We are talking about each view and widget having its own DOM, isn't it safe to assume that all DOM elements for a particular view and/or widget can be loaded when the view/widget itself is loaded? We are still lazy loading in the sense that we wouldn't load an unloaded view/widget's DOM until it was necessary, but we don't have to lazy load within the view/widget itself. My short term solution in the last paragraph would sort of give us this now, since loading the root Titanium node would effectively load all nodes for the view.
  5. Russell McMahon 2012-05-22

    Widgets will have their own DOM so all the objects of the widget will be created on init. Widgets are created from markup using
    so I think we are okay with widgets. I was thinking like the original test sample we still could have a project broken into multiple html files just to make things easy. The user would be responsible for keeping ids unique and all the markup across all html files would be in the global dom. The original sample had a second window contained in it's own html file open when a button on the first window was pressed. I had loaded all the html from the . We had talked about having an include api so the markup could be injected directly into a div tree if desired.
  6. Tony Lukasavage 2012-05-22

    I recently removed the ti-include markup handling because the aim with the separate markup files I thought was to maintain encapsulation. It's the same principle which causes us to use commonjs. You can build modular UI components without having to worry about ID collisions, or exposing all of the underlying elements of a view when they don't need to be exposed. Is the idea now to _not_ create modular views via markup, but to instead have all markup views share the same global DOM? It just seems sort of contradictory to what we've preached with JS dev in best practices in terms of creating reusable components. Do we not want to apply the same logic to HTML markup, or do we abide by the global nature of the ID attribute, whether it suits our current best practices or not?
  7. Tony Lukasavage 2012-05-30

    CSS in external, embedded, and inline markup is converted to JSON at compile-time. CSS specified in code at runtime will still need to be parsed.

JSON Source