Index: qtheme.template/trunk/qthemetemplate/localcommands/subtemplates.py
===================================================================
--- qtheme.template/trunk/qthemetemplate/localcommands/subtemplates.py	(revision 145)
+++ qtheme.template/trunk/qthemetemplate/localcommands/subtemplates.py	(revision 148)
@@ -71,2 +71,32 @@
         vars['css_resource_content'] = file(vars['css_file_path'],'rb').read()
 
+
+class JSSubTemplate(QThemeSubTemplate):
+    """
+    A Plone JS resource skeleton
+    """
+    _template_dir = 'templates/jsresource'
+    summary = "A Plone 3 JS resource template"
+    
+
+    vars = [
+      var('js_resource_name', 'Name of JS resource', default="foo.js"),
+      var('js_file_path', 'Path to JS file'),
+      var('jsreg_inline', 'Optional.Boolean', default="False"),
+      var('jsreg_cacheable', '', default="True"),
+      var('jsreg_compression', 'Compression type.Possible:none,safe,full,safe-encode,full-encode',
+          default="safe"),
+      var('jsreg_cookable', 'Boolean, aka merging allowed', default="True"),
+      var('jsreg_enables', 'Optional.Boolean', default="1"),
+      var('jsreg_expression', 'Optional.A tal condition.', default=""),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """ Set 'js_resource_content' value from js_file_path
+        """
+        
+        if not os.path.isfile(vars['js_file_path']):
+            raise ValueError('%s - wrong file path for js resource' % \
+                             vars['js_file_path'] )
+        vars['js_resource_content'] = file(vars['js_file_path'],'rb').read()
+
Index: qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/configure.zcml_insert
===================================================================
--- qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/configure.zcml_insert	(revision 148)
+++ qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/configure.zcml_insert	(revision 148)
@@ -0,0 +1,5 @@
+    <browser:resourceDirectory
+        name="${namespace_package}.${namespace_package2}.${package}.scripts"
+        directory="scripts"
+        layer=".interfaces.IThemeSpecific"
+        />
Index: qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/+js_resource_name+_tmpl
===================================================================
--- qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/+js_resource_name+_tmpl	(revision 148)
+++ qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/+js_resource_name+_tmpl	(revision 148)
@@ -0,0 +1,1 @@
+${js_resource_content}
Index: qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/README.txt_tmpl
===================================================================
--- qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/README.txt_tmpl	(revision 148)
+++ qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/browser/scripts/README.txt_tmpl	(revision 148)
@@ -0,0 +1,61 @@
+README for the 'browser/scripts/' directory
+===============================================
+
+This folder is a Zope 3 Resource Directory acting as a repository for
+scripts.
+
+Its declaration is located in 'browser/configure.zcml':
+
+    <!-- Resource directory for scripts -->
+    <browser:resourceDirectory
+        name="${namespace_package}.${namespace_package2}.${package}.scripts"
+        directory="scripts"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+A script placed in this directory (e.g. 'foo.js') can be accessed from
+this relative URL:
+
+    "++resource++${namespace_package}.${namespace_package2}.${package}.scripts/foo.js"
+
+Note that it might be better to register each of these resources separately if
+you want them to be overridable from zcml directives.
+
+The only way to override a resource in a resource directory is to override the
+entire directory (all elements have to be copied over).
+
+A Zope 3 browser resource declared like this in 'browser/configure.zcml':
+
+    <browser:resource
+        name="foo.js"
+        file="scripts/foo.js"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+can be accessed from this relative URL:
+
+    "++resource++foo.js"
+
+Notes
+-----
+
+* Scripts registered as Zope 3 resources might be flagged as not found in
+  the 'portal_js' tool if the layer they are registered for doesn't match the
+  default skin set in 'portal_skins'.
+  This can be confusing but it must be considered as a minor bug in the JS
+  registry instead of a lack in the way Zope 3 resources are handled in
+  Zope 2.
+
+* There might be a way to interpret DTML from a Zope 3 resource view.
+  Although, if you need to use DTML for setting values in a script (the
+  same way as in default Plone scripts where values are read from
+  'base_properties'), it is much easier to store it in a directory that is
+  located in the 'skins/' folder of your package, registered as a File System
+  Directory View in the 'portal_skins' tool, and added to the layers of your
+  skin.
+
+* Customizing/overriding scripts that are originally accessed from the
+  'portal_skins' tool (e.g. Plone default scripts) can be done inside that
+  tool only. There is no known way to do it with Zope 3 browser resources.
+  Vice versa, there is no known way to override a Zope 3 browser resource from
+  a skin layer in 'portal_skins'.
Index: qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/profiles/default/jsregistry.xml_insert
===================================================================
--- qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/profiles/default/jsregistry.xml_insert	(revision 148)
+++ qtheme.template/trunk/qthemetemplate/localcommands/templates/jsresource/profiles/default/jsregistry.xml_insert	(revision 148)
@@ -0,0 +1,13 @@
+#<?xml version="1.0"?>
+#<object name="portal_javascripts">
+#
+# <!-- -*- extra stuff goes here -*- -->
+#
+ <javascript
+    id="++resource++${namespace_package}.${namespace_package2}.${package}.scripts/${js_resource_name}"
+    inline="${jsreg_inline}" cacheable="${jsreg_cacheable}" compression="${jsreg_compression}"
+    cookable="${jsreg_cookable}" enabled="${jsreg_enables}"
+    expression="${jsreg_expression}"
+    />
+
+#</object>
Index: qtheme.template/trunk/qthemetemplate/templates/qplone3_theme/+namespace_package+/+namespace_package2+/+package+/profiles/default/jsregistry.xml_tmpl
===================================================================
--- qtheme.template/trunk/qthemetemplate/templates/qplone3_theme/+namespace_package+/+namespace_package2+/+package+/profiles/default/jsregistry.xml_tmpl	(revision 145)
+++ qtheme.template/trunk/qthemetemplate/templates/qplone3_theme/+namespace_package+/+namespace_package2+/+package+/profiles/default/jsregistry.xml_tmpl	(revision 148)
@@ -6,4 +6,6 @@
 #end if
 <object name="portal_javascripts">
+
+ <!-- -*- extra stuff goes here -*- -->
 
 #if str($include_doc) == 'True'
@@ -27,5 +29,4 @@
     enabled="True" expression=""  inline="False"/>
 -->
-
 #end if
 </object>
Index: qtheme.template/trunk/setup.py
===================================================================
--- qtheme.template/trunk/setup.py	(revision 145)
+++ qtheme.template/trunk/setup.py	(revision 148)
@@ -30,4 +30,5 @@
           skin_sublayer = qthemetemplate.localcommands.subtemplates:SkinSublayerSubTemplate
           css_resource = qthemetemplate.localcommands.subtemplates:CSSSubTemplate
+          js_resource = qthemetemplate.localcommands.subtemplates:JSSubTemplate
 
       # -*- Entry points: -*-
