Ticket #837 (closed feature: fixed)

Opened 14 years ago

Last modified 9 years ago

Refactoring CSS and JavaScript declaration

Reported by: bdelbosc Owned by: gracinet
Priority: P1 Milestone: CPS 3.5.2
Component: CPSDefault Version: TRUNK
Severity: critical Keywords: css js javascript


Refactoring CSS and JavaScript? declaration

At the moment the current situation is that all the CSS and JavaScript? declarations are almost done in 2 files: default.css and functions.js in CPSDefault while every CPS Products should be able to declare one or more css and javascript files.

So we should set up a framework that will take in charge the subscription of products' CSS and JS files and their rendering.

From those multiple CSS and JS files this framework will generate only one unique CSS file and one unique JS file.

This framework should keep a common stylesheet_properties.props for the sake of factorization.


  • each product will have its own CSS and JS files defined in itself and not in CPSDefault.
  • the generated unique CSS file and JS file will be smaller than the current files than currently include unused products' styles.

Change History

comment:1 Changed 14 years ago by fguillaume

Note that Plone has such a framework. It's called ResourceRegistries ( http://svn.plone.org/view/plone/ResourceRegistries/trunk/)

comment:2 Changed 14 years ago by fguillaume

Note also that we have the problem of providing appropriate javascript to the widgets themselves.

comment:3 Changed 14 years ago by jmorliaguet

oui, c'est une bonne idée.

je vais essayer de voir les cas possibles, mais de manière générale:

  • dans le cas des portlets, le code javascript est généré en fonction

des portlets effectivement affichés sur la page (voir par.ex le code javascript de la searchbox). Donc tout ce qui est autour de la partie centrale de l'écran (c.ad les portlets) est déjà géré par cpsskins/cpsportlets. Le code CSS statique pourrait être enregistré de manière plus générique.

sinon dans la partie centrale :

  • pour les formulaires (login_form, search_form...), il suffit d'avoir

un forms.css, forms.js commun dans CPSDefault, et l'équivalent dans CPSDocument pour l'édition et l'affichage des documents.

  • il est possible d'associer les css/js aux produits installés, mais

c'est pas forcément optimal. Peut-être qu'il serait mieux d'inclure les css/js en fonction du content-type affiché (chat / webmail / calendar, ...).

le 'portal_css' de Plone2.1 par exemple a un champ "Expression" pour l'inclusion conditionnelle des fichiers css (mais il manque la partie javascript).

comment:4 Changed 14 years ago by ebarroca

  • Owner changed from trac to tziade
  • Milestone changed from unspecified to CPS 3.4.1

comment:5 Changed 13 years ago by sfermigier

  • Milestone changed from CPS 3.4.1 to CPS 3.4.2

Il believe this is a work in progress by tziade (Nuxeo JS library).

comment:6 Changed 13 years ago by scamps

In the ticket #1757 I've suggested to include widget javascript requeriments in the widget render function itself, so the widget will not depend on javascript includes done by the template where it is used. One way to implement that could be to have an "importModule" function, able to detect if a javascript file has already included, and loading each file just once. As an example of that way of work, there is the loadScript function in CPSPortlets/browser/tree.pt, or the importModule function defined in the init.js of jsolait javascript library.

comment:7 Changed 13 years ago by madarche

  • Owner changed from tziade to madarche
  • Milestone changed from CPS 3.4.3 to CPS 3.4.4

comment:8 Changed 13 years ago by jmorliaguet

considering javascript resources, there is a simple optimization that can be done:

for a given site, go through all portlets, gather the javascript resources into a single file and place them in a global "per site" cache. The cache needs to be invalidated when a portlet is modified / added / removed.

Note that some existing sites might break (in cases where the javascript code is dependent on the actual HTML content of the page, this can happen), so this ought to be implemented as a new option for instance in the theme's tool (for example: [x] use a global file for javascript resources).

that's a "pull" model since you collect all resources from existing portlets. The advantage is that it is easy to implement, it only requires small modifications from the existing code, the drawback is that it can lead to a large javascript file, but thanks to the server-side cache and the browser cache / gzip possibilities it really doesn't matter.

the other model is to push resources into the <head> of the page, it is the way I would implement it today, as long as the result of the concatenation of all the resources can be easily cached per key (that's the case in nxthemes where resources are per theme/page/perspective/mode).

for CSS the issue is different since portlets do not declare CSS resources

comment:9 Changed 11 years ago by gracinet

  • Owner changed from madarche to gracinet
  • Status changed from new to assigned

It's time to tackle this long standing issue. Here's the summary of a recent discussion with madarche.

The most urgent use case imho is the one of widgets. Up to now, there is an hardcoded list of resources to load in cpsdocument_edit_form meaning that integration of a new js-enabled widget must add some resource to this list. This is somehow acceptable for core cps widgets (calendar), barely acceptable for integration projects (terminal in the dependency tree, they can override) and totaly inacceptable for generic but optional CPS components (FCKEditor, TinyMCE, tomorrow CPSTramline).

We are against the idea of generation of one big file because:

  • it's not dynamic enough, some libraries intended for different pages/modes might conflict;
  • it's a big burden for first connection, even with http caching (think of portals with a public side)

What we'll implement is a simple transient registry cached in the request so that widgets can register resource uris and pages like cpsdocument_edit_form can use it to include the needed javascript. This is close to what scamps suggests above. Of course it has keys for to distinguish between widgets, portlets and the like.

Same thing for css files, of course.

The above url for Plone Registry is outdated. Here's the  tutorial I just found. I believe it's still not dynamical enough. Resource requesting has to be done close to where it's been used. The static cases can be handled by the dynamical engine through persitence. For instance, we could add stylesheet properties to layouts and/or widgets and they would be requested by the generic code in CPSSchemas. This way, an integration product could add its specific stylesheet in a cleaner way than stuffing classes in custom.css

I have yet to take a look at how this works with CPSSkins/CPSPortlets, but I think it's less critical for now.

Everything would be so much simpler if page rendering were based on accumulators within Zope 2 !

comment:10 Changed 10 years ago by gracinet

  • Priority changed from P2 to P1
  • Severity changed from normal to major
  • Milestone changed from CPS 3.5.0 to CPS 3.5.1

comment:11 Changed 9 years ago by gracinet

  • Type changed from enhancement to task
  • Milestone changed from CPS 3.5.1 to CPS 3.5.2

Like all true changes after rc1, it will have to wait a bit.

comment:12 Changed 9 years ago by gracinet

  • Type changed from task to feature
  • Severity changed from major to critical

comment:13 Changed 9 years ago by gracinet

It just occurred to me that such a system could start in a simple form and be used right away. It's just a matter of deciding that this is the standard system. It can become more fully featered later.

So, CPSUtil.resourceregistry does the registration job by category and the Text Widget requires TinyMCE javascript source, in the widget category, of course. In turn cpsdocument_edit_form calls it again to dump the resources that have been required by the widgets.

One cas of harmful override of cpsdocument_edit_form has been avoided thanks to this in CPSTramline (#2222)

We can create more categories afterwards, and more importantly clean the existing templates of hardcoded stuff.

comment:14 Changed 9 years ago by gracinet

  • Status changed from assigned to closed
  • Resolution set to fixed

Time to close, lots of enhancements can be made, including leveraging more Zope 3/ZTK style ways of doing, but that'll tracked the time come in new tickets.

Note: See TracTickets for help on using tickets.