2

I'm looking into Google's stylesheet renaming feature and I'm not sure how to rewrite my jquery selectors. I didn't find the doc very clear on that.

If I have some code that looks like this:

<div class="MyClass"></div>
<div id="MyID"></div>

$('.MyClass').someFunc();
$('#MyID').someFunc();

How must the HTML and javascript be written so that CSS renaming will work?

Thanks for your suggestions.

Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
frenchie
  • 51,731
  • 109
  • 304
  • 510
  • Google Closure Stylesheet renaming is designed for use with the Google Closure Library. Specifically, you need `goog.getCssName` support. While it might be possible to make this work without Closure Library, there really isn't much information on that possibility yet. – Chad Killingsworth Sep 05 '12 at 13:46
  • Yes, I saw that goog.getCssName is mentioned. How does it work, specifically in conjunction with jquery? Is it used just within the compiler or does it also need to be included in the page's output? – frenchie Sep 05 '12 at 14:47
  • That was my point. I don't know that it does/will work with jQuery. – Chad Killingsworth Sep 05 '12 at 15:07

1 Answers1

20

For Closure-stylesheets to work in combination with an external library like jQuery, you will need to use the Closure-library as well to add support for goog.getCssName. However, because Closure-Library is written to make maximum use of the dead code elimination of Closure-compiler, only a very small amount of the library code will be included in the final output (about 1KB in this example).

Step 1 - Setup your project

You'll need the following tools:

Step 2 - Setup Your Source Files

Stylesheet Source (sample.gss)

@def BG_COLOR              rgb(235, 239, 249);

@def DIALOG_BORDER_COLOR   rgb(107, 144, 218);
@def DIALOG_BG_COLOR       BG_COLOR;

.MyClass {
  background-color: BG_COLOR;
  height:100px;
}

#MyId {
  background-color: DIALOG_BG_COLOR;
  border: 1px solid DIALOG_BORDER_COLOR;
  height:100px;
}

Closure Template Source (sample.soy)

{namespace ClosureSample}

/**
 * SampleHtml
 */
{template .SampleHtml autoescape="false"}
    <div class="{css MyClass}"></div>
{/template}

Javascript Source (sample.js)

goog.require('ClosureSample');
document.write(ClosureSample.SampleHtml());

$(function() {
    $('.' + goog.getCssName('MyClass')).css('background-color', 'pink');
});

HTML Source (development.htm)

<!DOCTYPE html>
<html>
<head>
  <title>Closure stylesheets with External Library</title>
  <link rel="Stylesheet" media="all" href="sample.css" />
  <script type="text/javascript" src="sample_renaming_map.js"></script>
  <script type="text/javascript" src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
  <script type="text/javascript">
    goog.require('goog.soy');
    goog.require('goog.string.StringBuffer');
  </script>
  <script type="text/javascript" src="soyutils_usegoog.js"></script>
  <script type="text/javascript" src="sample-templates.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>
  <script type="text/javascript" src="sample.js"></script>
  <div id="MyId"></div>
</body>
</html>

Step 3 - Compile your Stylesheet and Templates

Using the tools downloaded from the templates and stylesheet projects, you'll need to compile the sample.gss and sample.soy files. Here's the commands used for this sample:

java -jar closure-stylesheets.jar \
    --pretty-print \
    --output-file sample.css \
    --output-renaming-map-format CLOSURE_UNCOMPILED \
    --rename CLOSURE \
    --output-renaming-map sample_renaming_map.js \
    sample.gss

java -jar SoyToJsSrcCompiler.jar \
    --shouldProvideRequireSoyNamespaces \
    --shouldGenerateJsdoc \
    --outputPathFormat {INPUT_FILE_NAME_NO_EXT}.js \
    --cssHandlingScheme goog \
    sample.soy

With these files, you can test the renaming during development. See the example.

Step 4 - Compile the Project for Production

First recompile your stylesheets to produce a renaming map using the "CLOSURE_COMPILED" option:

java -jar closure-stylesheets.jar \
    --output-file sample.css \
    --output-renaming-map-format CLOSURE_COMPILED \
    --rename CLOSURE \
    --output-renaming-map sample_renaming_map.js \
    sample.gss

Then you will need to calculate the Closure-library dependency files and compile all of the source javascript files into a single source.

Note: since jQuery is not compatible with ADVANCED_OPTIMIZATIONS of Closure-compiler, it will not be included as input. Instead, reference the appropriate jQuery extern file found in the Closure-compiler contrib/externs folder.

The calcdeps.py script in the Closure-library project can be used to also call the Closure-compiler on the input files it determines.

python calcdeps.py \
    -i sample.js \
    -p PATH_TO_CLOSURE_LIBRARY_FOLDER \
    -p sample-templates.js \
    -o compiled \
    -c compiler.jar \
    -f --js=sample_renaming_map.js
    -f --compilation_level=ADVANCED_OPTIMIZATIONS \
    -f --warning_level=VERBOSE \
    -f --externs=jquery-1.7-externs.js \
    -f --js_output_file=sample_compiled.js

See the final result: compiled version.

Final Notes

As you can see, using Google Closure Stylesheets requires not only pieces of the entire Closure-tools suite, but is quite involved.

  • Outputing the HTML required use of Google Closure-templates. In this contrived example I used a document.write call to output the HTML with the properly renamed class, however there are more elegant and maintainable techniques for production code.
  • Closure-stylesheets does not rename ID selectors, therefore the code for an ID is not affected.
  • For ease of viewing, the compiled example references the jQuery library off of the Google CDN. However, it would be equally valid to concatenate the jQuery library and the compiled source into a single source JS file.
Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
  • Wow I'm up-voting this purely on effort! You must really like Google closure =P – Jon Sep 07 '12 at 15:42
  • I'm a regular contributor to the Closure-compiler project and it was a very interesting question. The original question author was correct; documentation for such uses is very sparse. – Chad Killingsworth Sep 07 '12 at 15:43
  • Thank you SOOOOO much! The doc is written with a "what-is" perspective but people need docs written from a "how-to" perspective like you did! Step 1: do this, step 2: do that, step n: you're done. I do want to ask a follow-up question. I'm writing a single-page app where most of the HTML is generated at run-time, with data coming in the form of ajaxed json strings. The only HTML that comes out of the server is the initial "skeleton" HTML. If I put this initial HTML in a string and use .html() in the doc.ready function, will that avoid using Closure Template and the soy file? Thanks!! – frenchie Sep 07 '12 at 19:09
  • Yes - instead of using SoyTemplates, you could do something like: `jQuery('#id').html('
    ')`
    – Chad Killingsworth Sep 07 '12 at 19:28
  • Ok, thank you very much for your answer and your work on Google Closure. And please spread the word: we don't want "what-is" documentations, we need "how-to" documentations!!! – frenchie Sep 07 '12 at 20:09
  • Quick follow-up question: I was wondering if you could check if the compiler going to work with $('#MyDivID .MyClass') or should these types of selectors be rewritten as $('#MyDivID').find('.MyClass') – frenchie Sep 13 '12 at 22:32
  • You would need to write it as either `$('#MyDivID.' + goog.getCssName('MyClass'))` or as `$('#MyDivID').find(goog.getCssName('MyClass'))`. Either should work. – Chad Killingsworth Sep 14 '12 at 16:08
  • ok, thanks for the follow up and keep up the closure project going: it's pretty amazing I'd say! Next up: I put 2 files into the compiler (one .js file and one .css file) and the magic happens without anything else to do (ie no need for goog.getCssName('MyClass')). This functionality would be for edge cases where the files are for an HTML5 single-page app where the HTML is entirely generated at runtime using javascript (ie. no need for closure template soy file). Would be nice... Thanks a lot for your answer!! – frenchie Sep 17 '12 at 22:58
  • it would be great if you can me this answer with correct download paths. – pregmatch Oct 16 '15 at 12:46
  • and i am getting sample-templates.js not found. – pregmatch Oct 16 '15 at 12:47
  • I would expect from someone who is working in google to write docs, to have good samples. most of the time i find their docs and code just one big mess who no one can understand. – pregmatch Oct 16 '15 at 12:54
  • @pregmatch I do not - nor have I ever - worked at Google. This answer is 3 years old, the projects have migrated to github and the download urls have changed. At stackoverflow you can suggest edits to answers which is much more constructive than leaving complaints in comments. – Chad Killingsworth Oct 16 '15 at 13:24
  • I did not mean anything bad to say about you of course. Its just so hard to read their docs, projects are moving to github, docs are no longer valid. it just big mess as far as i am concern. – pregmatch Oct 16 '15 at 13:41