From 5f6d9658336274ae964d8207522ad24957c15a4f Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sat, 3 Aug 2024 20:34:01 +0200 Subject: [PATCH 1/7] Replace Pegdown with Commonmark --- pom.xml | 13 ++++++--- .../google/gwt/site/markdown/MDHelper.java | 4 +-- .../gwt/site/markdown/MDTranslater.java | 27 ++++++++++++------- .../com/google/gwt/site/markdown/Util.java | 5 ++-- .../site/markdown/toc/TocFromMdCreator.java | 27 ++++++++++++------- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 994e05558..b022bcf8f 100644 --- a/pom.xml +++ b/pom.xml @@ -131,11 +131,18 @@ - org.pegdown - pegdown - 1.4.2 + org.commonmark + commonmark + + 0.21.0 + + org.commonmark + commonmark-ext-gfm-tables + + 0.21.0 + commons-io commons-io diff --git a/src/main/java/com/google/gwt/site/markdown/MDHelper.java b/src/main/java/com/google/gwt/site/markdown/MDHelper.java index 3db7bc47f..d007db819 100644 --- a/src/main/java/com/google/gwt/site/markdown/MDHelper.java +++ b/src/main/java/com/google/gwt/site/markdown/MDHelper.java @@ -15,8 +15,6 @@ import java.io.File; -import org.pegdown.PegDownProcessor; - import com.google.gwt.site.markdown.fs.FileSystemTraverser; import com.google.gwt.site.markdown.fs.MDParent; import com.google.gwt.site.markdown.toc.TocCreator; @@ -107,7 +105,7 @@ public MDHelper create() throws MDHelperException { // read template TOC if parameter is provided if (templateTocFile != null) { - templateToc = new PegDownProcessor().markdownToHtml(readFile(templateTocFile)); + templateToc = MDTranslater.markDownToHtml(readFile(templateTocFile)); } created = true; diff --git a/src/main/java/com/google/gwt/site/markdown/MDTranslater.java b/src/main/java/com/google/gwt/site/markdown/MDTranslater.java index afb2cb846..d85ef7f2e 100644 --- a/src/main/java/com/google/gwt/site/markdown/MDTranslater.java +++ b/src/main/java/com/google/gwt/site/markdown/MDTranslater.java @@ -17,23 +17,21 @@ import com.google.gwt.site.markdown.fs.MDParent; import com.google.gwt.site.markdown.toc.TocCreator; -import org.apache.commons.io.FileUtils; -import org.pegdown.Extensions; -import org.pegdown.PegDownProcessor; +import org.commonmark.Extension; +import org.commonmark.ext.gfm.tables.TablesExtension; +import org.commonmark.node.*; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; import java.io.File; import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; +import java.util.Collections; import java.util.List; +import java.util.Set; public class MDTranslater { - private static final int PEG_DOWN_FLAGS = Extensions.SMARTYPANTS | Extensions.AUTOLINKS | - Extensions.FENCED_CODE_BLOCKS | Extensions.TABLES | Extensions.DEFINITIONS; private static final String SEPARATOR = File.separator; - private PegDownProcessor pegDownProcessor = new PegDownProcessor(PEG_DOWN_FLAGS, Long - .MAX_VALUE); private final TocCreator tocCreator; @@ -63,7 +61,7 @@ private void renderTree(MDNode node, MDParent root) throws TranslaterException { } else { String markDown = getNodeContent(node.getPath()); - String htmlMarkDown = pegDownProcessor.markdownToHtml(markDown); + String htmlMarkDown = markDownToHtml(markDown); String toc = tocCreator.createTocForNode(root, node); @@ -86,6 +84,15 @@ private void renderTree(MDNode node, MDParent root) throws TranslaterException { } + protected static String markDownToHtml(String markDown) { + Set extensions = Collections.singleton(TablesExtension.create()); + Parser parser = Parser.builder() + .extensions(extensions).build(); + Node document = parser.parse(markDown); + HtmlRenderer renderer = HtmlRenderer.builder().extensions(extensions).build(); + return renderer.render(document); + } + private String getEditUrl(String path) { // TODO you should support more than one template if (path.endsWith("markdown/index.md")) { diff --git a/src/main/java/com/google/gwt/site/markdown/Util.java b/src/main/java/com/google/gwt/site/markdown/Util.java index 55d58303d..449d7d2d4 100644 --- a/src/main/java/com/google/gwt/site/markdown/Util.java +++ b/src/main/java/com/google/gwt/site/markdown/Util.java @@ -19,13 +19,14 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; public class Util { public static String getStringFromFile(File file) throws IOException { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); - return IOUtils.toString(fileInputStream, "UTF-8"); + return IOUtils.toString(fileInputStream, StandardCharsets.UTF_8); } finally { IOUtils.closeQuietly(fileInputStream); } @@ -35,7 +36,7 @@ public static void writeStringToFile(File file, String content) throws IOExcepti FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); - IOUtils.write(content, fileOutputStream); + IOUtils.write(content, fileOutputStream, StandardCharsets.UTF_8); } finally { IOUtils.closeQuietly(fileOutputStream); } diff --git a/src/main/java/com/google/gwt/site/markdown/toc/TocFromMdCreator.java b/src/main/java/com/google/gwt/site/markdown/toc/TocFromMdCreator.java index 24e9f7312..0a8165ef9 100644 --- a/src/main/java/com/google/gwt/site/markdown/toc/TocFromMdCreator.java +++ b/src/main/java/com/google/gwt/site/markdown/toc/TocFromMdCreator.java @@ -16,10 +16,9 @@ import com.google.gwt.site.markdown.fs.MDNode; import com.google.gwt.site.markdown.fs.MDParent; +import java.util.Arrays; import java.util.List; -import org.parboiled.common.StringUtils; - public class TocFromMdCreator implements TocCreator { public String createTocForNode(MDParent root, MDNode node) { @@ -49,17 +48,17 @@ private void render(MDNode node, StringBuffer buffer, MDNode tocNode) { } // Use 4 spaces to indent
  • 's, so as we have room for indenting
      's - String margin = StringUtils.repeat(' ', 4 * node.getDepth()); + String margin = spaces(4 * node.getDepth()); if (node.isFolder()) { MDParent mdParent = node.asFolder(); if (node.getDepth() != 0) { - buffer.append(margin + "
    • "); + buffer.append(margin).append("
    • "); buffer.append(""); buffer.append(node.getDisplayName()); buffer.append("\n"); - buffer.append(margin + "
        \n"); + buffer.append(margin).append("
          \n"); } List children = mdParent.getChildren(); @@ -68,8 +67,8 @@ private void render(MDNode node, StringBuffer buffer, MDNode tocNode) { } if (node.getDepth() != 0) { - buffer.append(margin + "
        \n"); - buffer.append(margin + "\n"); + buffer.append(margin).append("
      \n"); + buffer.append(margin).append("
    • \n"); } } else { StringBuffer relativeUrl = new StringBuffer(); @@ -85,11 +84,19 @@ private void render(MDNode node, StringBuffer buffer, MDNode tocNode) { relativeUrl.append(node.getRelativePath()); - buffer.append(margin + "
    • "); + buffer.append(margin).append("
    • "); // TODO escape HTML - buffer.append("" + node.getDisplayName() + ""); + buffer.append("") + .append(node.getDisplayName()).append(""); buffer.append("
    • \n"); } } + + private String spaces(int count) { + final byte[] spaceBytes = new byte[count]; + Arrays.fill(spaceBytes, (byte) ' '); + return new String(spaceBytes); + } } From 78e259057d52cccbd961263353d112439de462b8 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sat, 3 Aug 2024 23:20:27 +0200 Subject: [PATCH 2/7] Do not rely on definition list extension --- .../doc/latest/DevGuideI18nMessages.md | 125 +++++++++--------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/src/main/markdown/doc/latest/DevGuideI18nMessages.md b/src/main/markdown/doc/latest/DevGuideI18nMessages.md index e6fbc3dea..c4d4c53f2 100644 --- a/src/main/markdown/doc/latest/DevGuideI18nMessages.md +++ b/src/main/markdown/doc/latest/DevGuideI18nMessages.md @@ -91,67 +91,74 @@ An error is returned because the message template in the properties file expects In addition to the formatting supported by [MessageFormat](http://java.sun.com/j2se/1.5.0/docs/api/java/text/MessageFormat.html), GWT supports a number of extensions. -`{name,text}` -: A "static argument", which is simply `text`, except that it appears - in translation output as if it were a placeholder named `name`. - `text` is always terminated by the next "}". This is - useful to keep non-translated code out of what the translator sees, for example - HTML markup: - - ``` - @DefaultMessage("Welcome back, {startBold,}{0}{endBold,}") - ``` - -`{0,list}` or `{0,list,format...}` -: Format a `List` or array using locale-specific punctuation. For +
      +
      {name,text}
      +
      +A "static argument", which is simply text, except that it appears +in translation output as if it were a placeholder named name. +text is always terminated by the next "}". This is +useful to keep non-translated code out of what the translator sees, for example +HTML markup: + +``` +@DefaultMessage("Welcome back, {startBold,}{0}{endBold,}") +``` +
      +
      {0,list} or {0,list,format...}
      +
      +Format a List or array using locale-specific punctuation. For example, in English, lists would be formatted like this: -: | # of Items | Sample Output | - | :--------: | ------------- | - | 0 | _(empty string)_ | - | 1 | a | - | 2 | a and b | - | 3 | a, b, and c | - -: Note that only the locale-default separator and the logical conjuctive form is - supported -- there is currently no way to produce a list like "a; b; or c". -: See the [plurals documentation](DevGuideI18nPluralForms.html#Lists) for how this interacts with plural support. - The format following the `list` tag, if any, describes how each list - element is formatted. Ie, `{0,list}` means every element is formatted - as if by `{0}`, `{0,list,number,#,##}` as if by - `[0,number,#,##}`, etc. - -`{0,localdatetime,skeleton}` -: Format a date/time in a locale-specific format using the supplied skeleton - pattern. The order of the pattern characters doesn't matter, and spaces or other separators don't - matter. The localized pattern will contain the same fields (but may change - `MMM` into `LLL` for example) and the same count of each. -: If one of the predefined formats are not sufficient, you will be much - better off using a skeleton pattern so you will include the items you want - but still get a localized format. -: For example, if you used `{0,date,MM/dd/yy}` to format a date, you - get exactly that pattern in every locale, which is going to cause confusion for - those users who expect `dd/MM/yy`. Instead, you can use - `{0,localdatetime,MMddyy}` and you will get properly localized patterns - for each locale. - -`{0,localdatetime,predef:PREDEF_NAME}` -: Use a locale-specific predefined format -- see [DateTimeFormat.PredefinedFormat](/javadoc/latest/com/google/gwt/i18n/client/DateTimeFormat.PredefinedFormat.html)" - for possible values, example: `{0,localdatetime,predef:DATE_SHORT}`. - -extra formatter arguments -: Some formatters accept additional arguments. These are added to the main format specification, separated by a colon -- for example: - `{0,list,number:curcode=USD,currency}` says to use the default currency format for list elements, but use USD (US Dollars) for the currency code. You - can also supply a dynamic argument, such as `{0,localdatetime:tz=$tz,predef:DATE_FULL}`, which says the timezone to - use is supplied by a parameter `TimeZone tz` supplied to the method. - Where supported, multiple arguments can be supplied like `{0,format:arg1=val:arg2=val}`. - -: Currently supported arguments: - -: | Format | Argument Name | Argument Type | Description | - | ---------------------------- | ------------- | ------------- | ----------- | - | number | curcode | `String` | Currency code to use for currency formatting | - | date, time, or localdatetime | tz | `TimeZone` | Time zone to use for date/time formatting | +| # of Items | Sample Output | +| :--------: | ------------- | +| 0 | _(empty string)_ | +| 1 | a | +| 2 | a and b | +| 3 | a, b, and c | + +Note that only the locale-default separator and the logical conjuctive form is +supported -- there is currently no way to produce a list like "a; b; or c". +See the [plurals documentation](DevGuideI18nPluralForms.html#Lists) for how this interacts with plural support. +The format following the list tag, if any, describes how each list +element is formatted. Ie, {0,list} means every element is formatted +as if by `{0}`, {0,list,number,#,##} as if by +[0,number,#,##}, etc. +
      +
      {0,localdatetime,skeleton}
      +
      +Format a date/time in a locale-specific format using the supplied skeleton +pattern. The order of the pattern characters doesn't matter, and spaces or other separators don't +matter. The localized pattern will contain the same fields (but may change +MMM into LLL for example) and the same count of each. +If one of the predefined formats are not sufficient, you will be much +better off using a skeleton pattern so you will include the items you want +but still get a localized format. +For example, if you used {0,date,MM/dd/yy} to format a date, you +get exactly that pattern in every locale, which is going to cause confusion for +those users who expect dd/MM/yy. Instead, you can use +{0,localdatetime,MMddyy} and you will get properly localized patterns +for each locale. +
      +
      {0,localdatetime,predef:PREDEF_NAME}
      +
      +Use a locale-specific predefined format -- see [DateTimeFormat.PredefinedFormat](/javadoc/latest/com/google/gwt/i18n/client/DateTimeFormat.PredefinedFormat.html)" + for possible values, example: {0,localdatetime,predef:DATE_SHORT}. +
      +
      extra formatter arguments
      +
      Some formatters accept additional arguments. These are added to the main format specification, separated by a colon -- for example: + {0,list,number:curcode=USD,currency} says to use the default currency format for list elements, but use USD (US Dollars) for the currency code. You + can also supply a dynamic argument, such as {0,localdatetime:tz=$tz,predef:DATE_FULL}, which says the timezone to + use is supplied by a parameter TimeZone tz supplied to the method. + Where supported, multiple arguments can be supplied like {0,format:arg1=val:arg2=val}. + +Currently supported arguments: + +| Format | Argument Name | Argument Type | Description | + | ---------------------------- | ------------- | ------------- | ----------- | + | number | curcode | `String` | Currency code to use for currency formatting | + | date, time, or localdatetime | tz | `TimeZone` | Time zone to use for date/time formatting | +
      +
      ## Using Annotations From 7919a0c458392d8433a9ff8f21a0335f6d19fa50 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sun, 4 Aug 2024 00:19:29 +0200 Subject: [PATCH 3/7] Use HTML entity for mdash --- .../markdown/articles/dynamic_host_page.md | 2 +- .../markdown/articles/mvp-architecture-2.md | 2 +- .../articles/security_for_gwt_applications.md | 30 ++++++------ .../articles/using_gwt_for_json_mashups.md | 22 ++++----- src/main/markdown/community-group-charter.md | 4 +- src/main/markdown/doc/latest/DevGuide.md | 48 +++++++++---------- src/main/markdown/doc/latest/DevGuideA11y.md | 2 +- src/main/markdown/doc/latest/DevGuideHtml5.md | 8 ++-- .../doc/latest/DevGuideHtml5Storage.md | 4 +- .../doc/latest/DevGuideI18nMessages.md | 6 +-- .../doc/latest/DevGuideI18nPluralForms.md | 4 +- .../markdown/doc/latest/DevGuideSecurity.md | 6 +-- .../doc/latest/DevGuideSecuritySafeHtml.md | 2 +- src/main/markdown/doc/latest/DevGuideUi.md | 22 ++++----- src/main/markdown/doc/latest/FAQ_Server.md | 2 +- src/main/markdown/learnmore-sdk.md | 2 +- src/main/markdown/release-notes.md | 8 ++-- 17 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/main/markdown/articles/dynamic_host_page.md b/src/main/markdown/articles/dynamic_host_page.md index 599598f06..3a6508f8e 100644 --- a/src/main/markdown/articles/dynamic_host_page.md +++ b/src/main/markdown/articles/dynamic_host_page.md @@ -41,7 +41,7 @@ Let's examine everything that happens here if the user isn't logged in: 1. Your app is requested and your GWT host page (YourModule.html) is downloaded 2. module.nocache.js is requested by the page and is downloaded 3. MD5.cache.html is selected based on the browser and is downloaded -4. Your module loads and makes a GWT-RPC call to check if the user is logged in -- since they're not, they are redirected to the login page +4. Your module loads and makes a GWT-RPC call to check if the user is logged in — since they're not, they are redirected to the login page That's up to **four** server requests (depending on what is cached) just to send your user to the login page. And step 3 consists of diff --git a/src/main/markdown/articles/mvp-architecture-2.md b/src/main/markdown/articles/mvp-architecture-2.md index a9079d627..5ee39c611 100644 --- a/src/main/markdown/articles/mvp-architecture-2.md +++ b/src/main/markdown/articles/mvp-architecture-2.md @@ -752,7 +752,7 @@ public class ContactsViewImpl extends Composite implements ContactsView { } ``` -## Code Splitting -- Only the relevant parts please +## Code Splitting — Only the relevant parts please Up to this point we've discussed how code maintainability and testing are benefits of an MVP-based application. One other benefit that may go overlooked diff --git a/src/main/markdown/articles/security_for_gwt_applications.md b/src/main/markdown/articles/security_for_gwt_applications.md index 6363aaa1f..bfd845dbd 100644 --- a/src/main/markdown/articles/security_for_gwt_applications.md +++ b/src/main/markdown/articles/security_for_gwt_applications.md @@ -36,13 +36,13 @@ build a basic image gallery application by writing some JavaScript code that ins immediately loads the image as if it had been present in the original page; if you delete (or hide) an `` tag, the browser removes it from the display. -Essentially, the SOP lets JavaScript code do anything that the original HTML page could have done -- it just prevents that JavaScript from sending data to a different server, or from reading or writing data belonging to a different server. +Essentially, the SOP lets JavaScript code do anything that the original HTML page could have done — it just prevents that JavaScript from sending data to a different server, or from reading or writing data belonging to a different server. ### Leaking Data The text above said, "prevents JavaScript from sending data to a different server." Unfortunately, that's not strictly true. In fact it is possible to send data to a different server, although it might be more accurate to say "leak." -JavaScript is free to add new resources -- such as `` tags -- to the current page. You +JavaScript is free to add new resources — such as `` tags — to the current page. You probably know that you can cause an image hosted on foo.com to appear inline in a page served up by bar.com. Indeed, some people get upset if you do this to their images, since it uses their bandwidth to serve an image to your web visitor. But, it's a feature of HTML, and since HTML can do it, so can JavaScript. Normally you would view this as a read-only operation: the browser requests an image, and the server sends the data. The browser didn't upload anything, so no data can be lost, right? Almost, but not quite. The browser _did_ upload something: namely, the URL of the image. Images use standard URLs, and any URL can have query parameters encoded in it. A legitimate use case for this might be a page hit counter image, where a CGI on the server selects an appropriate image based on a query parameter and streams the data to the user in response. Here is a reasonable (though hypothetical) URL that could return a hit-count image showing the number '42': @@ -52,7 +52,7 @@ http://site.domain.tld/pagehits?count=42 ``` In the static HTML world, this is perfectly reasonable. After all, the server is not going to -send the client to a web site that will leak the server's or user's data -- at least, not on +send the client to a web site that will leak the server's or user's data — at least, not on purpose. Because this technique is legal in HTML, it's also legal in JavaScript, but there is an unintended consequence. If some evil JavaScript code gets injected into a good web page, it can construct `` tags and add them to the page. @@ -142,7 +142,7 @@ Probably the most common way that web sites manage sessions is via browser cooki The problem with this approach is that session cookies don't expire when the user leaves the site (they expire either when the browser closes or after some period of time). Since the browsers will include cookies with any request to your server regardless of context, if your users are logged in, it's possible for other sites to trigger an action on your server. This is frequently referred to as "Cross-Site Request Forging" or XSRF (or sometimes CSRF). -The sites most vulnerable to XSRF attacks, perhaps ironically, are those that have already embraced the service-oriented model. Traditional non-AJAX web applications are HTML-heavy and require multi-page UI operations by their very nature. The Same-Origin Policy prevents an XSRF attacker from _reading_ the results of its request, making it impossible for an XSRF attacker to navigate a multi-page process. The simple technique of requiring the user to click a confirmation button -- when properly implemented -- is enough to foil an XSRF attack. +The sites most vulnerable to XSRF attacks, perhaps ironically, are those that have already embraced the service-oriented model. Traditional non-AJAX web applications are HTML-heavy and require multi-page UI operations by their very nature. The Same-Origin Policy prevents an XSRF attacker from _reading_ the results of its request, making it impossible for an XSRF attacker to navigate a multi-page process. The simple technique of requiring the user to click a confirmation button — when properly implemented — is enough to foil an XSRF attack. Unfortunately, eliminating those sorts of extra steps is one of the key goals of the AJAX programming model. AJAX lets an application's UI logic run in the browser, which in turn lets communications with the server become narrowly defined operations. For instance, you might develop corporate HR application where the server exposes a URL that lets browser clients email a user's list of employee data to someone else. Such services are operation-oriented, meaning that a single HTTP request is all it takes to do something. @@ -150,7 +150,7 @@ Since a single request triggers the operation, the XSRF attacker doesn't need to ### JSON and XSRF -So far we've seen the one-two punch from XSS and XSRF. Sadly, there's _still_ more. These days, JSON (JavaScript Object Notation) is the new hotness -- and indeed, it's very hot. It's a clever, even elegant, technique. It also performs well, since it uses low-level (meaning: fast) browser support to handle parsing. It's also easy to program to, since the result is a JavaScript object, meaning you get object serialization almost for free. Unfortunately, with this powerful technique comes very substantial risks to your code; if you choose to use JSON with your GWT application, it's important to understand those risks. +So far we've seen the one-two punch from XSS and XSRF. Sadly, there's _still_ more. These days, JSON (JavaScript Object Notation) is the new hotness — and indeed, it's very hot. It's a clever, even elegant, technique. It also performs well, since it uses low-level (meaning: fast) browser support to handle parsing. It's also easy to program to, since the result is a JavaScript object, meaning you get object serialization almost for free. Unfortunately, with this powerful technique comes very substantial risks to your code; if you choose to use JSON with your GWT application, it's important to understand those risks. At this point, you'll need to understand JSON; check out the [json.org](http://json.org) site if you aren't familiar with it yet. A cousin of JSON is "JSON with Padding" or JSONP, so you'll also want to be familiar with that. Here's the earliest discussion of JSONP that we could find: [Remote JSON - JSONP](http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/). @@ -172,7 +172,7 @@ As bad as XSS and XSRF are, JSON gives them room to breathe, so to speak, which ` var result = { 'data': ['foo', 'bar'] };` -* A string containing a JSON object passed as the parameter to a function call -- that is, the JSONP model. +* A string containing a JSON object passed as the parameter to a function call — that is, the JSONP model. Example: @@ -180,16 +180,16 @@ As bad as XSS and XSRF are, JSON gives them room to breathe, so to speak, which The last two examples are most useful when returned from a server as the response to a `"); @@ -157,7 +157,7 @@ writer.append("Hello, world!"); Now your GWT code can access the data using JSNI, like so: -``` +```java public native String getEmail() /*-{ return $wnd.info['email']; }-*/; @@ -166,7 +166,7 @@ public native String getEmail() /*-{ Alternatively, you can take advantage of GWT's [Dictionary](/javadoc/latest/com/google/gwt/i18n/client/Dictionary.html) class: -``` +```java public void onModuleLoad() { // Looks for a JS variable called "info" in the global scope Dictionary info = Dictionary.getDictionary("info"); @@ -182,7 +182,7 @@ worthwhile to consider using a templating language like JSP to make your code more readable. Here's our example as a JSP page instead of a servlet: -``` +```jsp @@ -212,7 +212,7 @@ servlet: You can make this JSP page your welcome file by specifying it in your web.xml file: -``` +```xml gwt-hosting.jsp diff --git a/src/main/markdown/articles/elemental.md b/src/main/markdown/articles/elemental.md index cf3e4675c..c4d69cf5b 100644 --- a/src/main/markdown/articles/elemental.md +++ b/src/main/markdown/articles/elemental.md @@ -33,7 +33,7 @@ Elemental uses Java interfaces to hide most of the generated overlay types it us can be obtained by the `Window` or `Document` interfaces. Here is a simple example to play a sound using the Web Audio API. -``` +```java package com.myapp; import elemental.client.*; import elemental.dom.*; diff --git a/src/main/markdown/articles/gss_migration.md b/src/main/markdown/articles/gss_migration.md index 8129280e5..35854e3eb 100644 --- a/src/main/markdown/articles/gss_migration.md +++ b/src/main/markdown/articles/gss_migration.md @@ -25,7 +25,7 @@ Enabling GSS will tell the GWT compiler to use GSS for all CssResource interfaces. This flag can either be “false” (default) or “true”. -``` +```xml ``` @@ -35,7 +35,7 @@ If GSS is enabled and the GWT compiler finds a .css file, it will first convert this file to gss and then feed it into GSS on the fly. -``` +```xml ``` @@ -60,7 +60,7 @@ All of Google’s application have been using GSS instead of CSS since mid 2015. This would be invalid: -``` +```java // Invalid use since css and gss are mixed one method @Source({"def.css", "converted.gss"}) MyCssResource css(); @@ -80,7 +80,7 @@ MyCssResource css(); turn off auto conversion: -``` +```xml ``` @@ -98,7 +98,7 @@ turn off auto conversion: 6. Turn off auto conversion for app: -``` +```xml ``` @@ -110,7 +110,7 @@ Since UiBinder has no notion of a file extension we extended UiBinder to allow for an extra attribute on the style tag. To use GSS in UiBinder you have to add gss=”true”. -``` +```xml /* In here you can now use GSS */ @@ -121,7 +121,7 @@ Note: Like on CssResource css and gss can not be mixed here. If you importing a inside of the style element: -``` +```xml /* Need to use GSS here now! */ @@ -136,7 +136,7 @@ You can also control the default for CSS / GSS in all UiBinder fields by setting a configuration property: -``` +```xml ``` @@ -156,8 +156,8 @@ at all. You can run the tool like this: -``` -$ java -cp gwt-user.jar com.google.gwt.resources.converter.Css2Gss +```shell +java -cp gwt-user.jar com.google.gwt.resources.converter.Css2Gss fileToConvert.css ``` @@ -179,8 +179,8 @@ In order to get around this limitation the converter allows you to specify a list of css files to be parsed for building up scope: -``` -$ java -cp gwt-user.jar com.google.gwt.resources.converter.Css2Gss -scope +```shell +java -cp gwt-user.jar com.google.gwt.resources.converter.Css2Gss -scope foo.css,bar.css fileToConvert.css ``` diff --git a/src/main/markdown/articles/gwt-iphone.md b/src/main/markdown/articles/gwt-iphone.md index e5c4d2dd8..0e00b8d0a 100644 --- a/src/main/markdown/articles/gwt-iphone.md +++ b/src/main/markdown/articles/gwt-iphone.md @@ -126,7 +126,7 @@ allows you to implement a "deferred Iterator". This will avoid blocking the UI event loop while you create UI elements from a list of data objects: -``` +```java final List objects = ....; DeferredCommand.addCommand(new IncrementalCommand() { Iterator i = objects.iterator(); diff --git a/src/main/markdown/articles/mvp-architecture-2.md b/src/main/markdown/articles/mvp-architecture-2.md index a9079d627..13b5c6cb2 100644 --- a/src/main/markdown/articles/mvp-architecture-2.md +++ b/src/main/markdown/articles/mvp-architecture-2.md @@ -24,7 +24,7 @@ To start things out, let's take a look at the code that constructs our main ContactList view. Previously we programmatically setup the UI within the ContactsView constructor: -``` +```java public class ContactsView extends Composite implements ContactsPresenter.Display { ... public ContactsView() { @@ -70,11 +70,9 @@ The first step towards a UiBinder-way of doing things is to move this code into a Contacts.ui.xml file and perform the associated transformations. As mentioned in previous chapters, constructing UiBinder-based UIs allows you to do so in a declarative way that resembles HTML more than straight Java code. -To that extent, the result is the following: - -``` -ContactsView.ui.xml +To that extent, the result is the file `ContactsView.ui.xml` with the following content: +```xml @@ -108,7 +106,7 @@ amount of margin so that things aren't placed too close together. The ContactsView constructor and members are then reduced to the following: -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... @UiTemplate("ContactsView.ui.xml") @@ -145,7 +143,7 @@ Presenter interface that allows our ContactsView to callback into the presenter when it receives a click, select or other event. The Presenter interface defines the following: -``` +```java public interface Presenter { void onAddButtonClicked(); void onDeleteButtonClicked(); @@ -161,7 +159,7 @@ up is to have our ContactsPresenter implement the Presenter interface, and then register itself with the underlying view. To register itself, we'll need our ContactsView to expose a setPresenter() method: -``` +```java private Presenter presenter; public void setPresenter(Presenter presenter) { this.presenter = presenter; @@ -171,7 +169,7 @@ private Presenter presenter; Now we can take a look at how we'll wire up the UI interactions within the ContactsView via the UiHandler annotation: -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... @UiHandler("addButton") @@ -214,7 +212,7 @@ methods that should be called when a Widget has a "ui:field" attribute set to "addButton", "deleteButton", and "contactsTable". On the ContactsPresenter side of the fence we end up with the following: -``` +```java public class ContactsPresenter implements Presenter { ... public void onAddButtonClicked() { @@ -254,8 +252,8 @@ the model to our views. In the case of our ContactsView, the presenter takes a list of DTOs (Data Transfer Objects) and constructs a list of Strings that it then passes to the view. -``` -public ContactsPresenter implements Presenter { +```java +public class ContactsPresenter implements Presenter { ... public void onSuccess(ArrayList result) { contactDetails = result; @@ -286,7 +284,7 @@ homogeneous within column borders. Doing so allows us to define a ColumnDefinition abstract class that houses the any type-specific code (this is the third party mentioned above). -``` +```java public abstract class ColumnDefinition { public abstract Widget render(T t); @@ -305,7 +303,7 @@ render() implementations and isClickable()/isSelectable() overrides, you can start see how we would define our layout. Let's take a look at how we would make this work with our Contacts sample. -``` +```java public class ContactsViewColumnDefinitions { List> columnDefinitions = new ArrayList>(); @@ -345,7 +343,7 @@ platform-specific ContactsViewColumnDefinitions class that is loaded (or injected using GIN) on a per-permutation basis. Regardless of the technique, we'll need to update our views such that we can set their ColumnDefinition(s). -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... private List> columnDefinitions; @@ -362,7 +360,7 @@ ContactsView. This is so that we can pass in a mocked ContactsView instance when testing our ContactsPresenter. Now in our AppController, when we create the ContactsView, we can initialize it with the necessary ColumnDefinition(s). -``` +```java public class AppController implements Presenter, ValueChangeHandler { ... public void onValueChange(ValueChangeEvent event) { @@ -393,7 +391,7 @@ labor. Mainly in the way we pass model data to the view. As mentioned above we were previously dumbing down the model into a list of Strings. With our ColumnDefinition(s) we can pass the model untouched. -``` +```java public class ContactsPresenter implements Presenter, ... private void fetchContactDetails() { @@ -412,7 +410,7 @@ public class ContactsPresenter implements Presenter, And our ContactsViewImpl has the following setRowData() implementation: -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... public void setRowData(List rowData) { @@ -437,7 +435,7 @@ doesn't stop there. Remember the isClickable() and isSelectable() methods? Well, let's take a look at how they work in conjunction with ClickEvents that are received within the view. -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... @UiHandler("contactsTable") @@ -502,7 +500,7 @@ getSelectedRows() with a SelectionModel that the presenter holds on to. The SelectionModel is nothing more than a wrapper around a list of model objects. -``` +```java public class SelectionModel { List selectedItems = new ArrayList(); @@ -527,7 +525,7 @@ public class SelectionModel { The ContactsPresenter holds on to an instance of this class and updates it accordingly, based on calls to onItemSelected(). -``` +```java public class ContactsPresenter implements Presenter, ... public void onItemSelected(ContactDetails contactDetails) { @@ -546,7 +544,7 @@ public class ContactsPresenter implements Presenter, When it needs to grab the list of selected items, for example when the user clicks the "Delete" button, it has them right at its disposal. -``` +```java public class ContactsPresenter implements Presenter, ... @@ -604,7 +602,7 @@ The changes are encompassed within our ContactsView.ui.xml file, as well as our setRowData() and onTableClicked() methods. First we'll need to update our ContactsView.ui.xml file to use a HTML widget rather than a FlexTable widget. -``` +```xml ... @@ -622,7 +620,7 @@ ContactsView.ui.xml file to use a HTML widget rather than a FlexTable widget. We'll also need to change the widget that we reference within our ContactsViewImpl class. -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... @UiField HTML contactsTable; @@ -631,7 +629,7 @@ public class ContactsViewImpl extends Composite implements ContactsView { Next we'll make the necessary changes to our setRowData() method. -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... public void setRowData(List rowData) { @@ -675,7 +673,7 @@ as your tables start to grow. Now let's take a look at the code used to sink events on the table. -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... @UiHandler("contactsTable") @@ -716,7 +714,7 @@ The other tweak we need to make is to update our shouldFireClickEvent() and shouldFireSelectEvent() to take as a parameter a TableCellElement rather than a HTMLTable.Cell. The implementation remains the same, as you can see below. -``` +```java public class ContactsViewImpl extends Composite implements ContactsView { ... private boolean shouldFireClickEvent(TableCellElement cell) { @@ -774,7 +772,7 @@ the user even logs in? Not really. It would be nice if we could simply grab the login code, and leave the rest for when we actually need it (e.g. after the user has logged in). Well we can, and here's how. -``` +```java public void onValueChange(ValueChangeEvent event) { String token = event.getValue(); diff --git a/src/main/markdown/articles/mvp-architecture.md b/src/main/markdown/articles/mvp-architecture.md index cbbe13ac9..d8b887f21 100644 --- a/src/main/markdown/articles/mvp-architecture.md +++ b/src/main/markdown/articles/mvp-architecture.md @@ -132,7 +132,7 @@ general flow, as shown in the following code, is: [presenters](#presenter) and supplying a [view](#view) that the presenter will drive. -``` +```java public class Contacts implements EntryPoint { public void onModuleLoad() { @@ -164,8 +164,7 @@ something meaningful, the [presenter](#presenter) is going to need to: In the case of our ContactsPresenter, we define the Display interface as such: -``` - +```java public class ContactsPresenter implements Presenter { ... public interface Display extends HasValue> { @@ -199,7 +198,7 @@ made without updating the view code. To show you how this works, let's look at the code that is executed upon receiving the list of Contacts from the server: -``` +```java public class ContactsPresenter implements Presenter { ... private void fetchContactDetails() { @@ -225,8 +224,7 @@ public class ContactsPresenter implements Presenter { To listen for UI events we have the following: -``` - +```java public class ContactsPresenter implements Presenter { ... public void bind() { @@ -259,7 +257,7 @@ public class ContactsPresenter implements Presenter { To respond to UI events, such as the user deleting a list of selected contacts, we have the following: -``` +```java public class ContactsPresenter implements Presenter { ... private void deleteSelectedContacts() { @@ -347,7 +345,7 @@ and pass in the [Event.Type](/javadoc/latest/com/google/web/bindery/event/shared as well as the handler that should be called when the event is fired. The code below shows how the AppController registers to receive EditContactEvents. -``` +```java public class AppController implements ValueChangeHandler { ... eventBus.addHandler(EditContactEvent.TYPE, @@ -377,8 +375,7 @@ we'll notify the rest of the app by calling the EventBus.fireEvent() method with a EditContactEvent() class that is initialized with the id of the contacts to be edited. -``` - +```java public class ContactsPresenter { ... display.getList().addClickHandler(new ClickHandler() { @@ -406,7 +403,7 @@ which is the case after the RPC has returned. Below is an example of the event that is fired upon successfully updating a contact. -``` +```java public class EditContactPresenter { ... private void doSave() { @@ -450,8 +447,7 @@ and declare its own [onValueChange()](/javadoc/latest/com/google/gwt/event/logic method. The interface and parameter are of type String because the History events are simply the tokens that are pushed onto the stack. -``` - +```java public class AppController implements ValueChangeHandler { ... public void onValueChange(ValueChangeEvent event) { @@ -464,7 +460,7 @@ public class AppController implements ValueChangeHandler { Next we'll need to register to receive History events, much like we registered for events coming off of the EventBus. -``` +```java public class AppController implements ValueChangeHandler { ... private void bind() { @@ -482,8 +478,7 @@ user bookmarked a specific state within your app) and route the user to the appropriate view. The AppController's go() method, which is called after everything has been wired up, is where we'll add this logic. -``` - +```java public class AppController implements ValueChangeHandler { ... public void go(final HasWidgets container) { @@ -504,7 +499,7 @@ meaningful within the onValueChange() method that is called whenever the user clicks the "Back" or "Forward" button. Using the getValue() of the event, we'll decide which view to show next. -``` +```java public class AppController implements ValueChangeHandler { ... public void onValueChange(ValueChangeEvent event) { @@ -549,8 +544,7 @@ Below is an example of how you can hook up the ContactsPresenter to the "Add Contact" button, fire the associated event upon receiving the click, and transition to the "Add Contact" view as a result. -``` - +```java public class ContactsPresenter implements Presenter { ... public void bind() { @@ -563,7 +557,7 @@ public class ContactsPresenter implements Presenter { } ``` -``` +```java public class AppController implements ValueChangeHandler { ... private void bind() { @@ -618,8 +612,7 @@ Each example is set up to test adding a list of ContactDetails, sorting those ContactDetails, and then verifying that the sorted list is correct. Taking a look at the ExampleJRETest, we have the following code. -``` - +```java public class ExampleJRETest extends TestCase { private ContactsPresenter contactsPresenter; private ContactsServiceAsync mockRpcService; @@ -654,7 +647,7 @@ our tests on GWTTestCase. We then created the same test using GWTTestCase. -``` +```java public class ExampleGWTTest extends GWTTestCase { private ContactsPresenter contactsPresenter; private ContactsServiceAsync rpcService; diff --git a/src/main/markdown/articles/security_for_gwt_applications.md b/src/main/markdown/articles/security_for_gwt_applications.md index 6363aaa1f..44cf29325 100644 --- a/src/main/markdown/articles/security_for_gwt_applications.md +++ b/src/main/markdown/articles/security_for_gwt_applications.md @@ -47,7 +47,7 @@ probably know that you can cause an image hosted on foo.com to appear inline in Normally you would view this as a read-only operation: the browser requests an image, and the server sends the data. The browser didn't upload anything, so no data can be lost, right? Almost, but not quite. The browser _did_ upload something: namely, the URL of the image. Images use standard URLs, and any URL can have query parameters encoded in it. A legitimate use case for this might be a page hit counter image, where a CGI on the server selects an appropriate image based on a query parameter and streams the data to the user in response. Here is a reasonable (though hypothetical) URL that could return a hit-count image showing the number '42': -``` +```text http://site.domain.tld/pagehits?count=42 ``` @@ -61,7 +61,7 @@ It is then free to construct a URL to any hostile domain, stick it in an `` make the request. It's not hard to imagine a scenario where the evil code steals some useful information and encodes it in the `` URL; an example might be a tag such as: -``` +```html ``` @@ -93,7 +93,7 @@ uge chunks of their lives thinking up ways to do this. The list of ways that evil code can get into an otherwise good page is endless. Usually they all boil down to unwary code that parrots user input back to the user. For instance, this Python CGI code is vulnerable: -``` +```python import cgi f = cgi.FieldStorage() name = f.getvalue('name') or 'there' @@ -108,7 +108,7 @@ print s The code is supposed to print a simple greeting, based on a form input. For instance, a URL like this one would print "Hello, Dan!": -``` +```text http://site.domain.tld/path?name=Dan ``` @@ -116,13 +116,13 @@ However, because the CGI doesn't inspect the value of the "name" variable, an at Here is some JavaScript that pops up an alert window: -``` +```html ``` That script code can be encoded into a URL such as this: -``` +```text http://site.domain.tld/path?name=Dan%3Cscript%20%3Ealert%28%22Hi%22%29%3B%3C/script%3E ``` @@ -158,25 +158,25 @@ As bad as XSS and XSRF are, JSON gives them room to breathe, so to speak, which * A JSON string returned as the response text from an XMLHTTPRequest call (or other request) - Examples: + Examples: - ` [ 'foo', 'bar' ]` + * ` [ 'foo', 'bar' ]` - ` { 'data': ['foo', 'bar'] }` + * ` { 'data': ['foo', 'bar'] }` - Typically these strings are parsed via a call to JavaScript's 'eval' function for fast decoding. + Typically these strings are parsed via a call to JavaScript's 'eval' function for fast decoding. * A string containing a JSON object assigned to a variable, returned by a server as the response to a ` ``` @@ -191,7 +191,7 @@ copy and place the required static resources in the final war output directory. For example, here is the build.xml file generated by the GWT webAppCreator script: -``` +```xml @@ -209,7 +209,7 @@ For example, here is the build.xml file generated by the GWT webAppCreator scrip Let's suppose that the static resources that you want to copy over are located in the src/com/myapp/resources folder. You could define a copy target that takes these resources and copies them over to the war output directory like so: -``` +```xml @@ -222,7 +222,7 @@ Let's suppose that the static resources that you want to copy over are located i Lastly, update the gwtc target to depend on the newly created copyresources target: -``` +```xml ``` diff --git a/src/main/markdown/doc/latest/FAQ_Server.md b/src/main/markdown/doc/latest/FAQ_Server.md index 332884e04..f3eed1a82 100644 --- a/src/main/markdown/doc/latest/FAQ_Server.md +++ b/src/main/markdown/doc/latest/FAQ_Server.md @@ -42,7 +42,7 @@ application, the `<`module`>`.nocache.js file would be bootstrapped by having th the `<`module`>`.nocache.js file. This is the standard bootstrap process to load a GWT application. The `<`script`>` tag that needs to be included in the main host HTML page is shown below: -``` +```html ``` @@ -63,7 +63,7 @@ To enable the cross-site linking simply add the following to your `.gwt.xml` and include a reference to your `.nocache.js` in your index.html as you normally would. -``` +```xml ``` @@ -120,7 +120,7 @@ You should definitely use `RequestBuilder` instead. If you are attempting to use the RequestBuilder class and are having problems, first check your module XML file to make sure that the HTTP module is inherited, as follows: -``` +```xml ``` diff --git a/src/main/markdown/doc/latest/FAQ_Troubleshooting.md b/src/main/markdown/doc/latest/FAQ_Troubleshooting.md index a9faadfb4..bde5862ea 100644 --- a/src/main/markdown/doc/latest/FAQ_Troubleshooting.md +++ b/src/main/markdown/doc/latest/FAQ_Troubleshooting.md @@ -33,7 +33,7 @@ FAQ - Troubleshooting After upgrading to GWT 1.5, you might see this exception: -``` +```text [ERROR] Uncaught exception escaped java.lang.AssertionError: Element may only be set once ``` @@ -60,7 +60,7 @@ the protected [AbsolutePanel(Element)](/javadoc/latest/com/google/gwt/user/clien Although you have successfully compiled the project class files in an IDE, when invoking the GWT compiler for the first time on a new project using one of the APIs provided with the GWT Google API, you come across an error similar to the following: -``` +```text $ ./gearsTest-compile Analyzing source in module 'com.example.gearsTest' [ERROR] Errors in '/Users/zundel/Documents/workspace2/galgwt-issue3/src/com/example/client/gearsTest.java' @@ -79,7 +79,7 @@ This can be resolved by updating the module XML file (.gwt.xml) in either of two For using the Gears package in GWT Google API, the appropriate line is: -``` +```xml ``` @@ -91,7 +91,7 @@ Window). You might run into the problem in the first place because the [ImageBundle](DevGuideUiImageBundles.html) feature triggers the GWT compiler to connect to an X11 Graphics Environment Window at compile time. If you don't have a DISPLAY environment variable set, it will issue the following error message: -``` +```text java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable. ``` @@ -103,7 +103,7 @@ in their underlying implementations, the GWT compiler will search for the DISPLA To avoid this error message, run the GWT compiler with the headless AWT option. -``` +```text -Djava.awt.headless=true ``` @@ -121,7 +121,7 @@ If you use a custom build process, you can also set the AWT headless option ther When compiling a project in GWT 1.5 or later, you may encounter problems with running out of memory. -``` +```text Compiling permutations Analyzing permutation #1 [ERROR] An internal compiler exception occurred @@ -156,7 +156,7 @@ To provide a virtual display: * Install Xvfb. * Start the Xvfb server and set the environment variable DISPLAY to use it. -``` +```shell export DISPLAY=:2 ``` * Run Xvfb without access control on display :2 @@ -164,7 +164,7 @@ export DISPLAY=:2 This command will only start Xvfb if it is not already started. Any GWT compiles and tests should set DISPLAY=:2 to use the virtual frame buffer. -``` +```shell ps -ef | grep Xvfb | grep -v grep >> /dev/null || Xvfb :2 -ac & ``` @@ -174,7 +174,7 @@ ps -ef | grep Xvfb | grep -v grep >> /dev/null || Xvfb :2 -ac & When testing a new RPC interface in development mode, receive a "resource not found" error. -``` +```text The development shell servlet received a request for 'rpcs/myService' in module 'com.example.RPCExample' Resource not found: rpcs/myService ``` @@ -191,7 +191,7 @@ The servlet engine could not find the server-side definition of your RPC method. * Is the server code path listed in the module XML file (_myApp_.gwt.xml)? * -``` +```xml ``` @@ -210,7 +210,7 @@ The servlet engine could not find the server-side definition of your RPC method. If you are using GWT RPC and upgrading from GWT 1.4 to GWT 1.5, you may see a stack trace similar to the following: -``` +```text javax.servlet.ServletException: Content-Type must be 'text/plain' with 'charset=utf-8' (or unspecified charset) at com.google.gwt.user.server.rpc.RemoteServiceServlet.readPayloadAsUtf8(RemoteServiceServlet.java: 119) at com.google.gwt.user.server.rpc.RemoteServiceServlet.doPost(RemoteServiceServlet.java: 178) @@ -259,7 +259,7 @@ Check the /Library/InputManagers folder. If there is a file named GearsEnabler.b When launching the GWT compiler or development mode, you may see the following exception. -``` +```text Exception in thread "main" java.lang.ExceptionInInitializerError Caused by: java.lang.RuntimeException: Installation problem detected, please reinstall GWT at com.google.gwt.util.tools.Utility.computeInstallationPath(Utility.java:322) @@ -295,7 +295,7 @@ Make sure you have: When running in development mode, receive the error: Unable to find type 'com.foo.client.MyApp'. -``` +```text Starting HTTP on port 8888 Finding entry point classes Unable to find type 'com.google.gwt.sample.stockwatcher.client.StockWatcher' @@ -337,7 +337,7 @@ If you take a peek at your `C:\Windows\System32\drivers\etc\hosts` file, you wil If you created your application using the [Google Plugin for Eclipse](https://developers.google.com/eclipse), you may have encountered the following stack trace: -``` +```text WARNING: Nested in java.lang.ExceptionInInitializerError: java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup) @@ -406,7 +406,7 @@ files as UTF-8. Thus your source files are not properly encoded in UTF-8. * Check any associated Java properties files (or other files where you've stored translations) to see if they are saved in UTF-8 format. * Check the HTML host page. If your web page content contains localized data, encode it as UTF-8 by adding the following tag to the `<`head`>` element. -``` +```html ` ``` diff --git a/src/main/markdown/doc/latest/FAQ_UI.md b/src/main/markdown/doc/latest/FAQ_UI.md index b70b9e93e..92de3b126 100644 --- a/src/main/markdown/doc/latest/FAQ_UI.md +++ b/src/main/markdown/doc/latest/FAQ_UI.md @@ -24,7 +24,7 @@ When you are working with complex layouts, it is sometimes difficult to understa As an example, suppose you were trying to create a layout with two buttons, one on the left side of the browser, and the other on the right side of the browser. Here's some code that attempts to do that: -``` +```java VerticalPanel vertPanel = new VerticalPanel(); DockPanel dockPanel = new DockPanel(); @@ -48,7 +48,7 @@ The first technique is to use a DOM inspection tool, such as [Firebug](http://ww Another technique you can use is to modify your GWT code to turn on borders on your panels (or other widgets.) -``` +```java VerticalPanel vertPanel = new VerticalPanel(); DockPanel dockPanel = new DockPanel(); @@ -68,7 +68,7 @@ VerticalPanel vertPanel = new VerticalPanel(); You can also use the associated CSS stylesheet to change the border properties. In this case, the stylesheet changes the colors of the borders to make them easier to tell apart: -``` +```css .dockPanel { border-color: orange; } @@ -84,7 +84,7 @@ Now you can see clearly where the outlines of each panel are: In this case, the outermost panel needs to be 100% width as well, so we change the code, hit _Refresh_ in the browser window: -``` +```java vertPanel.setWidth("100%"); ``` @@ -92,7 +92,7 @@ vertPanel.setWidth("100%"); This is closer to what we want, but it still isn't right. Now we need to change the cell alignment in the [DockPanel](/javadoc/latest/com/google/gwt/user/client/ui/DockPanel.html) instance: -``` +```java Button rightButton = new Button("rightButton"); dockPanel.add(rightButton, DockPanel.EAST); dockPanel.setCellHorizontalAlignment(rightButton, HasHorizontalAlignment.ALIGN_RIGHT); @@ -121,7 +121,7 @@ these values. These methods set the widget's CSS height and/or and width propert In standards mode, if an element (such as a `<`div`>`) is inside a table cell `<`td`>`, you cannot set the `<`div`>` height and width attributes as percentages. They are ignored. For example, the styles in the `<`div`>` element below is ignored in standards mode: -``` +```html
      webAppCreator -out foo -templates maven,sample,readme com.example.foo.Foo +```shell +webAppCreator -out foo -templates maven,sample,readme com.example.foo.Foo ``` The generated files are used as follows: @@ -74,24 +75,25 @@ The generated files are used as follows: _**Note**: because of a bug in GWT-2.7.0, it generates a broken `pom.xml`, hence, you have to modify the `` block to include the `` parameter:_ - - - - - com.google.gwt - gwt - ${gwtVersion} - import - pom - - - - +```xml + + + + + com.google.gwt + gwt + ${gwtVersion} + import + pom + + + +``` ### Creating an `Ant` project. -``` -~/Foo> webAppCreator -junit /path/to/junit-3.8.1.jar -out foo com.example.foo.Foo +```shell +webAppCreator -junit /path/to/junit-3.8.1.jar -out foo com.example.foo.Foo ``` The generated files are used as follows: @@ -114,7 +116,7 @@ Notice also that there are some properties that you might like to extract to a ` A command-line tool that generates scripts to help with [static string internationalization](DevGuideI18n.html#DevGuideStaticStringInternationalization), along with sample [properties files](DevGuideI18n.html#DevGuidePropertiesFiles). Modify the `.properties` files to suit your project. Run the generated `-i18n` script to (re)generate a Java interface for accessing the tags defined in your properties files. -``` +```text i18nCreator [-eclipse projectName] [-out dir] [-[no]overwriteFiles] \ [-[no]createConstantsWithLookup] [-[no]createMessages] \ [-[no]ignoreExistingFiles] interfaceName @@ -132,7 +134,7 @@ i18nCreator [-eclipse projectName] [-out dir] [-[no]overwriteFiles] \ ### Example -``` +```text ~/Foo> i18nCreator -eclipse Foo -createMessages com.example.foo.client.FooMessages Created file src/com/example/foo/client/FooMessages.properties Created file FooMessages-i18n.launch @@ -142,7 +144,7 @@ i18nCreator [-eclipse projectName] [-out dir] [-[no]overwriteFiles] \ Running `FooMessages-i18n` will generate an interface class in a file named `FooMessages.java` from `FooMessages.properties` that extends `Messages` (The messages will take parameters, substituting `{n}` with the nth parameter). -``` +```text ~/Foo> i18nCreator -eclipse Foo com.example.foo.client.FooConstants Created file src/com/example/foo/client/FooConstants.properties Created file FooConstants-i18n.launch diff --git a/src/main/markdown/doc/latest/polymer-tutorial/create.md b/src/main/markdown/doc/latest/polymer-tutorial/create.md index 20fdc6308..6f93e6eee 100644 --- a/src/main/markdown/doc/latest/polymer-tutorial/create.md +++ b/src/main/markdown/doc/latest/polymer-tutorial/create.md @@ -26,10 +26,12 @@ For the **TodoList** project, we'll need to run `webAppCreator` with the followi GWT webAppCreator will generate the project structure and the build script (maven pom.xml). - $ /full_path_to_gwt_sdk/webAppCreator \ - -templates maven,sample \ - -out TodoListApp \ - org.gwtproject.tutorial.TodoList + ```shell + $ /full_path_to_gwt_sdk/webAppCreator \ + -templates maven,sample \ + -out TodoListApp \ + org.gwtproject.tutorial.TodoList + ``` _**Tip**: If you include the GWT SDK folder in your PATH environment variable, you won't have to specify the full path._ @@ -39,9 +41,11 @@ For the **TodoList** project, we'll need to run `webAppCreator` with the followi To check that the project was created correctly start the new app in SuperDevMode. - $ cd TodoListApp - $ mvn war:exploded - $ mvn gwt:devmode + ```shell + $ cd TodoListApp + $ mvn war:exploded + $ mvn gwt:devmode + ``` _**Tip**: Since the created project is built with Maven, you can import it in Eclipse, IDEA, etc._ @@ -58,58 +62,68 @@ With the base project set up, we'll now add the necessary external dependencies. 1. Add the vaadin `gwt-polymer-elements` dependency to your project by editing the `pom.xml` file. - - com.vaadin.polymer - vaadin-gwt-polymer-elements - ${gwtPolymerVersion} - provided - + ```xml + + com.vaadin.polymer + vaadin-gwt-polymer-elements + ${gwtPolymerVersion} + provided + + ``` _**Note**: Replace the `${gwtPolymerVersion}` placeholder with the current version (as of this writing 1.0.2.0-alpha3) or add the corresponding property in your pom.xml_ 2. Update the gwt-maven-plugin configuration to support the experimental `JsInterop` feature. - - org.codehaus.mojo - gwt-maven-plugin - ... - - JS - ... - - - + ```xml + + org.codehaus.mojo + gwt-maven-plugin + ... + + JS + ... + + + ``` + _**Note**: JsInterop is an experimental flag in GWT-2.7.0 and you need to enable it explicitly. In future versions of GWT it will be enabled by default._ 3. Update `TodoList.gwt.xml` module file so that we can use the new gwt library. - - ... - - ... - + ```xml + + ... + + ... + + ``` 4. Update `TodoList.html` * Configure the `` viewport to handle mobile layouting. * Import the polyfill ` - - - - - + ```html + + + + + + + + + + + ``` 5. Remove `greetServlet` and its mapping in `WEB-INF/web-xml` - - - + + ```xml + + + ``` 6. Remove all unnecessary files. @@ -121,20 +135,22 @@ With the base project set up, we'll now add the necessary external dependencies. Replace the content of `TodoList.java` with - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.paper.widget.PaperButton; - - public class TodoList implements EntryPoint { - public void onModuleLoad() { - // Use Widget API to Create a - PaperButton button = new PaperButton("Press me!"); - button.setRaised(true); - RootPanel.get().add(button); - } - } + ```java + package org.gwtproject.tutorial.client; + + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.paper.widget.PaperButton; + + public class TodoList implements EntryPoint { + public void onModuleLoad() { + // Use Widget API to Create a + PaperButton button = new PaperButton("Press me!"); + button.setRaised(true); + RootPanel.get().add(button); + } + } + ``` _**Note**: The example above shows how to add a `PaperButton` element using the Widgets API._ diff --git a/src/main/markdown/doc/latest/polymer-tutorial/elements-applogic.md b/src/main/markdown/doc/latest/polymer-tutorial/elements-applogic.md index dc7d72cda..4a08958f6 100644 --- a/src/main/markdown/doc/latest/polymer-tutorial/elements-applogic.md +++ b/src/main/markdown/doc/latest/polymer-tutorial/elements-applogic.md @@ -7,24 +7,26 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 1. Create the *Add Item dialog* by adding the following markup to the `Main.ui.xml` file: - - ... - -

      Add Item

      - -
      - -
      -
      - Cancel - OK -
      -
      -
      + ```xml + + ... + +

      Add Item

      + +
      + +
      +
      + Cancel + OK +
      +
      +
      + ``` _**Tip**: You can use attributes to quickly define certain polymer actions such as `entry-animation='fade-in-animation'`._ @@ -32,29 +34,33 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 2. Add all the fields defined in the `Main.ui.xml` file to the `Main.java` class. - @UiField PaperDrawerPanelElement drawerPanel; - @UiField HTMLElement content; + ```java + @UiField PaperDrawerPanelElement drawerPanel; + @UiField HTMLElement content; - @UiField PaperFabElement addButton; - @UiField PaperDialogElement addItemDialog; - @UiField PaperInputElement titleInput; - @UiField PaperTextareaElement descriptionInput; - @UiField PaperButtonElement confirmAddButton; + @UiField PaperFabElement addButton; + @UiField PaperDialogElement addItemDialog; + @UiField PaperInputElement titleInput; + @UiField PaperTextareaElement descriptionInput; + @UiField PaperButtonElement confirmAddButton; + ``` 3. Add a click handler to the floating action button in the `Main` constructor. - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); + ```java + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); - addButton.addEventListener("click", new EventListener() { - @Override - public void handleEvent(Event event) { - addItemDialog.open(); - } - }); + addButton.addEventListener("click", new EventListener() { + @Override + public void handleEvent(Event event) { + addItemDialog.open(); } + }); + } + ``` - _**Note**: Because elements lack methods for handling GWT events, we cannot use `@UiHandler` annotations. Thus we have to configure events in the constructor._ + _**Note**: Because elements lack methods for handling GWT events, we cannot use `@UiHandler` annotations. Thus we have to configure events in the constructor._ 4. Reload the application @@ -66,131 +72,137 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas * `Item.ui.xml` - - -
      - -
      -

      - - Go to Google -

      -
      -
      -
      - - + ```xml + + +
      + +
      +

      + + Go to Google +

      +
      +
      +
      + + ``` + * `Item.java`: For simplicity, we will use this class as the item POJO. - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.shared.GWT; - import com.google.gwt.dom.client.DivElement; - import com.google.gwt.dom.client.Element; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.uibinder.client.UiField; - import com.vaadin.polymer.elemental.Event; - import com.vaadin.polymer.elemental.EventListener; - import com.vaadin.polymer.paper.element.PaperCheckboxElement; - - public class Item { + ```java + package org.gwtproject.tutorial.client; - private final DivElement element; + import com.google.gwt.core.shared.GWT; + import com.google.gwt.dom.client.DivElement; + import com.google.gwt.dom.client.Element; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.uibinder.client.UiField; + import com.vaadin.polymer.elemental.Event; + import com.vaadin.polymer.elemental.EventListener; + import com.vaadin.polymer.paper.element.PaperCheckboxElement; - interface ItemUiBinder extends UiBinder { - } + public class Item { - private static ItemUiBinder ourUiBinder = GWT.create(ItemUiBinder.class); - - @UiField Element title; - @UiField Element description; - @UiField PaperCheckboxElement done; - - public Item() { - element = ourUiBinder.createAndBindUi(this); - - done.addEventListener("iron-change", new EventListener() { - @Override - public void handleEvent(Event event) { - if (done.getActive()) { - title.addClassName("done"); - } else { - title.removeClassName("done"); - } - } - }); - } + private final DivElement element; - public String getTitle() { - return title.getInnerText(); - } - public void setTitle(String s) { - title.setInnerText(s); - } - public String getDescription() { - return description.getInnerText(); - } - public void setDescription(String s) { - description.setInnerText(s); - } - public boolean isDone() { - return done.getActive(); - } - public void setDone(boolean b) { - done.setActive(b); - } - public DivElement getElement() { - return element; - } - } + interface ItemUiBinder extends UiBinder { + } -6. Add the logic for creating items when we click the save button. + private static ItemUiBinder ourUiBinder = GWT.create(ItemUiBinder.class); - ... - private List items = new ArrayList<>(); + @UiField Element title; + @UiField Element description; + @UiField PaperCheckboxElement done; - public Main() { - ... - addButton.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - addItemDialog.open(); - } - }); + public Item() { + element = ourUiBinder.createAndBindUi(this); - confirmAddButton.addEventListener("click", new EventListener() { + done.addEventListener("iron-change", new EventListener() { + @Override public void handleEvent(Event event) { - if (!titleInput.getValue().isEmpty()) { - addItem(titleInput.getValue(), descriptionInput.getValue()); - // clear text fields - titleInput.setValue(""); - descriptionInput.setValue(""); + if (done.getActive()) { + title.addClassName("done"); + } else { + title.removeClassName("done"); } } }); } - private void addItem(String title, String description) { - Item item = new Item(); - item.setTitle(title); - item.setDescription(description); - content.appendChild(item.getElement()); - items.add(item); + public String getTitle() { + return title.getInnerText(); + } + public void setTitle(String s) { + title.setInnerText(s); + } + public String getDescription() { + return description.getInnerText(); + } + public void setDescription(String s) { + description.setInnerText(s); + } + public boolean isDone() { + return done.getActive(); + } + public void setDone(boolean b) { + done.setActive(b); + } + public DivElement getElement() { + return element; + } + } + ``` + +6. Add the logic for creating items when we click the save button. + + ```java + ... + private List items = new ArrayList<>(); + + public Main() { + ... + addButton.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + addItemDialog.open(); + } + }); + + confirmAddButton.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + if (!titleInput.getValue().isEmpty()) { + addItem(titleInput.getValue(), descriptionInput.getValue()); + // clear text fields + titleInput.setValue(""); + descriptionInput.setValue(""); } - ... + } + }); + } + + private void addItem(String title, String description) { + Item item = new Item(); + item.setTitle(title); + item.setDescription(description); + content.appendChild(item.getElement()); + items.add(item); + } + ... + ``` 7. Reload the application @@ -200,178 +212,185 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 8. Add the **Clear All** and **Clear Done** menu item handlers in the constructor. - public Main() { - ... - menuClearAll.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - closeMenu(); - // remove all child elements - while (content.hasChildNodes()) { - content.removeChild(content.getFirstChild()); - } - } - }); - - menuClearDone.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - closeMenu(); - - for (Item item : items) { - if (item.isDone()) { - content.removeChild(item.getElement()); - items.remove(item); - } - } - } - }); + ```java + public Main() { + ... + menuClearAll.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + closeMenu(); + // remove all child elements + while (content.hasChildNodes()) { + content.removeChild(content.getFirstChild()); } + } + }); + + menuClearDone.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + closeMenu(); - private void closeMenu() { - if (drawerPanel.getNarrow()) { - drawerPanel.closeDrawer(); + for (Item item : items) { + if (item.isDone()) { + content.removeChild(item.getElement()); + items.remove(item); } } - + } + }); + } + + private void closeMenu() { + if (drawerPanel.getNarrow()) { + drawerPanel.closeDrawer(); + } + } + ``` + _**Note**: The closeMenu() method is only useful if the application is viewed on a mobile device, or if your browser window is narrow enough for the side menu to collapse. Hence, we use this method to hide the menu after clicking on any menu item._ 9. The final `Main.java` should look like this - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.GWT; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.uibinder.client.UiField; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; - import com.vaadin.polymer.elemental.*; - import com.vaadin.polymer.paper.element.*; - - import java.util.ArrayList; - import java.util.List; - - public class Main extends Composite { - interface MainUiBinder extends UiBinder { - } + ```java + package org.gwtproject.tutorial.client; - private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); + import com.google.gwt.core.client.GWT; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.uibinder.client.UiField; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; + import com.vaadin.polymer.elemental.*; + import com.vaadin.polymer.paper.element.*; - @UiField PaperDrawerPanelElement drawerPanel; + import java.util.ArrayList; + import java.util.List; - @UiField PaperIconItemElement menuClearAll; - @UiField PaperIconItemElement menuClearDone; + public class Main extends Composite { + interface MainUiBinder extends UiBinder { + } - @UiField HTMLElement content; - @UiField PaperFabElement addButton; + private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); - @UiField PaperDialogElement addItemDialog; - @UiField PaperInputElement titleInput; - @UiField PaperTextareaElement descriptionInput; - @UiField PaperButtonElement confirmAddButton; + @UiField PaperDrawerPanelElement drawerPanel; - private List items = new ArrayList<>(); + @UiField PaperIconItemElement menuClearAll; + @UiField PaperIconItemElement menuClearDone; - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); + @UiField HTMLElement content; + @UiField PaperFabElement addButton; - addButton.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - addItemDialog.open(); - } - }); + @UiField PaperDialogElement addItemDialog; + @UiField PaperInputElement titleInput; + @UiField PaperTextareaElement descriptionInput; + @UiField PaperButtonElement confirmAddButton; - confirmAddButton.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - if (!titleInput.getValue().isEmpty()) { - addItem(titleInput.getValue(), descriptionInput.getValue()); - // clear text fields - titleInput.setValue(""); - descriptionInput.setValue(""); - } - } - }); + private List items = new ArrayList<>(); - menuClearAll.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - closeMenu(); - // remove all child elements - while (content.hasChildNodes()) { - content.removeChild(content.getFirstChild()); - } - } - }); - - menuClearDone.addEventListener("click", new EventListener() { - public void handleEvent(Event event) { - closeMenu(); - - for (Item item : items) { - if (item.isDone()) { - content.removeChild(item.getElement()); - items.remove(item); - } - } - } - }); + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); + + addButton.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + addItemDialog.open(); } - - private void addItem(String title, String description) { - Item item = new Item(); - item.setTitle(title); - item.setDescription(description); - content.appendChild(item.getElement()); - items.add(item); + }); + + confirmAddButton.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + if (!titleInput.getValue().isEmpty()) { + addItem(titleInput.getValue(), descriptionInput.getValue()); + // clear text fields + titleInput.setValue(""); + descriptionInput.setValue(""); + } + } + }); + + menuClearAll.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + closeMenu(); + // remove all child elements + while (content.hasChildNodes()) { + content.removeChild(content.getFirstChild()); + } } + }); - private void closeMenu() { - if (drawerPanel.getNarrow()) { - drawerPanel.closeDrawer(); + menuClearDone.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + closeMenu(); + + for (Item item : items) { + if (item.isDone()) { + content.removeChild(item.getElement()); + items.remove(item); + } } } + }); + } + + private void addItem(String title, String description) { + Item item = new Item(); + item.setTitle(title); + item.setDescription(description); + content.appendChild(item.getElement()); + items.add(item); + } + + private void closeMenu() { + if (drawerPanel.getNarrow()) { + drawerPanel.closeDrawer(); } + } + } + ``` 10. Your `TodoList.java` should look like this: - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - import com.vaadin.polymer.iron.element.IronIconElement; - import com.vaadin.polymer.paper.element.*; - - import java.util.Arrays; - - public class TodoList implements EntryPoint { - - public void onModuleLoad() { - Polymer.importHref(Arrays.asList( - "iron-icons/iron-icons.html", - PaperIconItemElement.SRC, - PaperRippleElement.SRC, - IronIconElement.SRC, - PaperDrawerPanelElement.SRC, - PaperHeaderPanelElement.SRC, - PaperToolbarElement.SRC, - PaperFabElement.SRC, - PaperDialogElement.SRC, - PaperTextareaElement.SRC, - PaperInputElement.SRC, - PaperButtonElement.SRC, - PaperCheckboxElement.SRC - ), new Function() { - public Object call(Object arg) { - startApplication(); - return null; - } - }); - - } + ```java + package org.gwtproject.tutorial.client; + + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.Polymer; + import com.vaadin.polymer.elemental.Function; + import com.vaadin.polymer.iron.element.IronIconElement; + import com.vaadin.polymer.paper.element.*; + + import java.util.Arrays; + + public class TodoList implements EntryPoint { + + public void onModuleLoad() { + Polymer.importHref(Arrays.asList( + "iron-icons/iron-icons.html", + PaperIconItemElement.SRC, + PaperRippleElement.SRC, + IronIconElement.SRC, + PaperDrawerPanelElement.SRC, + PaperHeaderPanelElement.SRC, + PaperToolbarElement.SRC, + PaperFabElement.SRC, + PaperDialogElement.SRC, + PaperTextareaElement.SRC, + PaperInputElement.SRC, + PaperButtonElement.SRC, + PaperCheckboxElement.SRC + ), new Function() { + public Object call(Object arg) { + startApplication(); + return null; + } + }); - private void startApplication() { - RootPanel.get().add(new Main()); - } + } + private void startApplication() { + RootPanel.get().add(new Main()); + } + } + ``` + 11. Reload the application * Add several items diff --git a/src/main/markdown/doc/latest/polymer-tutorial/elements-buildui.md b/src/main/markdown/doc/latest/polymer-tutorial/elements-buildui.md index a69485972..e3d60360a 100644 --- a/src/main/markdown/doc/latest/polymer-tutorial/elements-buildui.md +++ b/src/main/markdown/doc/latest/polymer-tutorial/elements-buildui.md @@ -12,95 +12,103 @@ In this chapter we'll build a modern looking UI for the **TodoList** application * `Main.java` - package org.gwtproject.tutorial.client; + ```java + package org.gwtproject.tutorial.client; - import com.google.gwt.core.client.GWT; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; + import com.google.gwt.core.client.GWT; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; - public class Main extends Composite { - interface MainUiBinder extends UiBinder { - } + public class Main extends Composite { + interface MainUiBinder extends UiBinder { + } - private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); + private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); - } + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); } - + } + ``` + * `Main.ui.xml` - - - - - - + ```xml + + + + + + + ``` 2. Add **menu items**. Now we can update the `Main.ui.xml` file by adding menu items. - - - - - -
      Clear All
      -
      - - -
      Clear Done
      -
      - - -
      Settings
      -
      - - -
      About
      -
      -
      -
      + ```xml + + + + + +
      Clear All
      +
      + + +
      Clear Done
      +
      + + +
      Settings
      +
      + + +
      About
      +
      +
      +
      + ``` _**Note:** Visit the original [polymer elements](https://elements.polymer-project.org/browse?package=paper-elements) documentation to learn and demo each component._ 3. Update the **entry point** to use our new screen. - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - import com.vaadin.polymer.iron.element.IronIconElement; - import com.vaadin.polymer.paper.element.PaperIconItemElement; - - import java.util.Arrays; - - public class TodoList implements EntryPoint { + ```java + package org.gwtproject.tutorial.client; - public void onModuleLoad() { - // We have to load icon sets before run application - Polymer.importHref(Arrays.asList( - PaperIconItemElement.SRC, - IronIconElement.SRC), new Function() { - public Object call(Object arg) { - // The app is executed when all imports succeed. - startApplication(); - return null; - } - }); + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.Polymer; + import com.vaadin.polymer.elemental.Function; + import com.vaadin.polymer.iron.element.IronIconElement; + import com.vaadin.polymer.paper.element.PaperIconItemElement; + + import java.util.Arrays; + + public class TodoList implements EntryPoint { + + public void onModuleLoad() { + // We have to load icon sets before run application + Polymer.importHref(Arrays.asList( + PaperIconItemElement.SRC, + IronIconElement.SRC), new Function() { + public Object call(Object arg) { + // The app is executed when all imports succeed. + startApplication(); + return null; } + }); + } - private void startApplication() { - RootPanel.get().add(new Main()); - } - } + private void startApplication() { + RootPanel.get().add(new Main()); + } + } + ``` _**Tip**: to facilitate the usage of webcomponents gwt-polymer-elements maintains a couple of static constants: `Element.TAG` and `Element.SRC`, to avoid memorizing tag names and import paths respectively._ @@ -115,35 +123,35 @@ In this chapter we'll build a modern looking UI for the **TodoList** application 1. Import **icon collections**. Polymer comes with several icon collections. Before a collection can be used, it has to be imported. In this example we'll be using the Iron set. In the code below, we use the `Polymer.importHref` utility method, and wait for the set to load before we run the application. + ```java + package org.gwtproject.tutorial.client; - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - - public class TodoList implements EntryPoint { - - public void onModuleLoad() { - // We have to load icon sets before run application - Polymer.importHref(Arrays.asList( - "iron-icons/iron-icons.html", - PaperIconItemElement.SRC, - IronIconElement.SRC), new Function() { - public Object call(Object arg) { - // The app is executed when all imports succeed. - startApplication(); - return null; - } - }); - } - - private void startApplication() { - RootPanel.get().add(new Main()); + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.Polymer; + import com.vaadin.polymer.elemental.Function; + + public class TodoList implements EntryPoint { + + public void onModuleLoad() { + // We have to load icon sets before run application + Polymer.importHref(Arrays.asList( + "iron-icons/iron-icons.html", + PaperIconItemElement.SRC, + IronIconElement.SRC), new Function() { + public Object call(Object arg) { + // The app is executed when all imports succeed. + startApplication(); + return null; } - } - + }); + } + + private void startApplication() { + RootPanel.get().add(new Main()); + } + } + ``` 2. Reload the application You should see all icons in the browser now. @@ -156,7 +164,7 @@ In this chapter we'll build a modern looking UI for the **TodoList** application * Add `` to each item in the `Main.ui.xml` file. * We need to add a few CSS style properties to the items, so that the ripple effect is constrained within the item area. - + ```xml @@ -189,38 +197,38 @@ In this chapter we'll build a modern looking UI for the **TodoList** application - + ``` 4. Don't forget to import the ripple effect in `TodoList.java`. + ```java + package org.gwtproject.tutorial.client; - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - - public class TodoList implements EntryPoint { - - public void onModuleLoad() { - // We have to load icon sets before run application - Polymer.importHref(Arrays.asList( - "iron-icons/iron-icons.html", - PaperIconItemElement.SRC, - IronIconElement.SRC, - PaperRippleElement.SRC), new Function() { - public Object call(Object arg) { - // The app is executed when all imports succeed. - startApplication(); - return null; - } - }); - } - - private void startApplication() { - RootPanel.get().add(new Main()); + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.Polymer; + import com.vaadin.polymer.elemental.Function; + + public class TodoList implements EntryPoint { + + public void onModuleLoad() { + // We have to load icon sets before run application + Polymer.importHref(Arrays.asList( + "iron-icons/iron-icons.html", + PaperIconItemElement.SRC, + IronIconElement.SRC, + PaperRippleElement.SRC), new Function() { + public Object call(Object arg) { + // The app is executed when all imports succeed. + startApplication(); + return null; } - } - + }); + } + + private void startApplication() { + RootPanel.get().add(new Main()); + } + } + ``` 5. Reload the application to see the ripple effect in action. Compare click reactions before and after adding `PaperRipple` effects. @@ -230,74 +238,76 @@ In this chapter we'll build a modern looking UI for the **TodoList** application 1. Layout the application with a Paper **Draw Panel**. The Paper elements collection includes a responsive drawer panel. It's a layout component that can be used in modern applications to make sure they behave nicely on both desktop and mobile devices. For more information, check out the paper-drawer-panel [demo](https://elements.polymer-project.org/elements/paper-drawer-panel?view=demo:demo/index.html). + ```xml + - - - - - -
      - - - - -
      Clear All
      - -
      - - -
      Clear Done
      - -
      - - -
      Settings
      - -
      - - -
      About
      - -
      -
      -
      -
      - - - - Todo List - - -
      -
      -
      -
      - -2. Add the *content panel* - - * Add a container for our todo items. - - - ... + + + +
      + + + + +
      Clear All
      + +
      + + +
      Clear Done
      + +
      + + +
      Settings
      + +
      + + +
      About
      + +
      +
      +
      Todo List - -
      -
      - ... - + + + + ``` +2. Add the *content panel* + + * Add a container for our todo items. + + ```xml + + ... +
      + + + + Todo List + + +
      + + +
      + ... + + ``` 3. Add the necessary HTML imports `PaperDrawerPanelElement.SRC, PaperHeaderPanelElement.SRC, PaperToolbarElement.SRC` in `TodoList.java`. @@ -321,34 +331,36 @@ We have two options: We'll use the 2nd approach, but be aware that it will include a new ` - ... -
      - - - - Todo List - -
      - -
      - ... - + + ```xml + + + ... +
      + + + + Todo List + +
      + +
      + ... + + ``` _**Note**: the `vertical`, `center-justified` and `layout` classes are provided by Polymer._ @@ -356,21 +368,23 @@ _**Note**: the `vertical`, `center-justified` and `layout` classes are provided Material Design applications use the characteristic floating button for the main action. In the Paper elements collection, this button is called [paper-fab][1]. - - -
      - ... - -
      -
      + ```xml + + +
      + ... + +
      +
      + ``` _**Tip**: In order to make Polymer process your style block add the `is="custom-style"` attribute._ @@ -381,110 +395,113 @@ _**Tip**: Take a look at [paper-fab][1] documentation for available custom styli ## Summary Finally your `Main.ui.xml` file should look like: - - - - - - -
      - - - - -
      Clear All
      - -
      - - -
      Clear Done
      - -
      - - -
      Settings
      - -
      - - -
      About
      - -
      -
      -
      -
      - - - - Todo List - -
      - - -
      - - - +```xml + + + + + +
      + + + + +
      Clear All
      + +
      + + +
      Clear Done
      + +
      + + +
      Settings
      + +
      + + +
      About
      + +
      +
      +
      +
      + + + + Todo List + +
      + + +
      + + + +``` Your `TodoList.java` should look like this: - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - import com.vaadin.polymer.iron.element.IronIconElement; - import com.vaadin.polymer.paper.element.*; - - import java.util.Arrays; - - public class TodoList implements EntryPoint { - - public void onModuleLoad() { - Polymer.importHref(Arrays.asList( - "iron-icons/iron-icons.html", - PaperIconItemElement.SRC, - PaperRippleElement.SRC, - IronIconElement.SRC, - PaperDrawerPanelElement.SRC, - PaperHeaderPanelElement.SRC, - PaperToolbarElement.SRC, - PaperFabElement.SRC - ), new Function() { - public Object call(Object arg) { - startApplication(); - return null; - } - }); - } - - private void startApplication() { - RootPanel.get().add(new Main()); +```java +package org.gwtproject.tutorial.client; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.user.client.ui.RootPanel; +import com.vaadin.polymer.Polymer; +import com.vaadin.polymer.elemental.Function; +import com.vaadin.polymer.iron.element.IronIconElement; +import com.vaadin.polymer.paper.element.*; + +import java.util.Arrays; + +public class TodoList implements EntryPoint { + + public void onModuleLoad() { + Polymer.importHref(Arrays.asList( + "iron-icons/iron-icons.html", + PaperIconItemElement.SRC, + PaperRippleElement.SRC, + IronIconElement.SRC, + PaperDrawerPanelElement.SRC, + PaperHeaderPanelElement.SRC, + PaperToolbarElement.SRC, + PaperFabElement.SRC + ), new Function() { + public Object call(Object arg) { + startApplication(); + return null; } - } + }); + } + + private void startApplication() { + RootPanel.get().add(new Main()); + } +} +``` If everything is OK, after reloading your app should look like this: diff --git a/src/main/markdown/doc/latest/polymer-tutorial/widgets-applogic.md b/src/main/markdown/doc/latest/polymer-tutorial/widgets-applogic.md index 276d3b57b..25261c647 100644 --- a/src/main/markdown/doc/latest/polymer-tutorial/widgets-applogic.md +++ b/src/main/markdown/doc/latest/polymer-tutorial/widgets-applogic.md @@ -7,35 +7,37 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 1. Create the **Add Item dialog** by adding the following markup to the Main.ui.xml file: - - ... - .content { - padding: 15px; - } - - .dialog { - min-width: 40%; - } - - - - ... - -

      Add Item

      - -
      - -
      -
      - Cancel - OK -
      -
      -
      + ```xml + + ... + .content { + padding: 15px; + } + + .dialog { + min-width: 40%; + } + + + + ... + +

      Add Item

      + +
      + +
      +
      + Cancel + OK +
      +
      +
      + ``` _**Tip**: You can use attributes to quickly define certain polymer actions such as `entry-animation='fade-in-animation'`._ @@ -43,19 +45,23 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 2. Add all the fields defined in the `Main.ui.xml` file to the `Main.java` class. - @UiField PaperDrawerPanel drawerPanel; - @UiField HTMLPanel content; + ```java + @UiField PaperDrawerPanel drawerPanel; + @UiField HTMLPanel content; - @UiField PaperDialog addItemDialog; - @UiField PaperInput titleInput; - @UiField PaperTextarea descriptionInput; + @UiField PaperDialog addItemDialog; + @UiField PaperInput titleInput; + @UiField PaperTextarea descriptionInput; + ``` 3. Bind the click handler method to the floating action button in the `Main.java` - @UiHandler("addButton") - protected void onAddButtonClick(ClickEvent e) { - addItemDialog.open(); - } + ```java + @UiHandler("addButton") + protected void onAddButtonClick(ClickEvent e) { + addItemDialog.open(); + } + ``` 4. Reload the application @@ -65,148 +71,153 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 6. Create a `UiBinder` widget for displaying items: `Item.ui.xml` and `Item.java` - * `Item.ui.xml` - - - - @external .done; - .item .done { - text-decoration: line-through; - } - .title { - padding-left: 20px; - font-size: 150%; - font-weight: normal; - } - - - -
      -

      - - Go to Google -

      -
      -
      -
      -
      - - * `Item.java`: For simplicity, we will use this class as the item POJO - - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.shared.GWT; - import com.google.gwt.dom.client.Element; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.uibinder.client.UiField; - import com.google.gwt.uibinder.client.UiHandler; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; - import com.vaadin.polymer.iron.widget.event.IronChangeEvent; - import com.vaadin.polymer.paper.widget.PaperCheckbox; - - public class Item extends Composite { - - interface ItemUiBinder extends UiBinder { - } - - private static ItemUiBinder ourUiBinder = GWT.create(ItemUiBinder.class); - - @UiField Element title; - @UiField Element description; - @UiField PaperCheckbox done; - - public Item() { - initWidget(ourUiBinder.createAndBindUi(this)); - } - - @UiHandler("done") - protected void change(IronChangeEvent ev) { - if (done.getActive()) { - title.addClassName("done"); - } else { - title.removeClassName("done"); - } - } - public String getTitle() { - return title.getInnerText(); - } - public void setTitle(String s) { - title.setInnerText(s); - } - public String getDescription() { - return description.getInnerText(); - } - public void setDescription(String s) { - description.setInnerText(s); - } - public boolean isDone() { - return done.getActive(); - } - public void setDone(boolean b) { - done.setActive(b); - } - } - + * `Item.ui.xml` + + ```xml + + + @external .done; + .item .done { + text-decoration: line-through; + } + .title { + padding-left: 20px; + font-size: 150%; + font-weight: normal; + } + + + +
      +

      + + Go to Google +

      +
      +
      +
      +
      + ``` + + * `Item.java`: For simplicity, we will use this class as the item POJO + + ```java + package org.gwtproject.tutorial.client; + + import com.google.gwt.core.shared.GWT; + import com.google.gwt.dom.client.Element; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.uibinder.client.UiField; + import com.google.gwt.uibinder.client.UiHandler; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; + import com.vaadin.polymer.iron.widget.event.IronChangeEvent; + import com.vaadin.polymer.paper.widget.PaperCheckbox; + + public class Item extends Composite { + + interface ItemUiBinder extends UiBinder { + } + + private static ItemUiBinder ourUiBinder = GWT.create(ItemUiBinder.class); + + @UiField Element title; + @UiField Element description; + @UiField PaperCheckbox done; + + public Item() { + initWidget(ourUiBinder.createAndBindUi(this)); + } + + @UiHandler("done") + protected void change(IronChangeEvent ev) { + if (done.getActive()) { + title.addClassName("done"); + } else { + title.removeClassName("done"); + } + } + public String getTitle() { + return title.getInnerText(); + } + public void setTitle(String s) { + title.setInnerText(s); + } + public String getDescription() { + return description.getInnerText(); + } + public void setDescription(String s) { + description.setInnerText(s); + } + public boolean isDone() { + return done.getActive(); + } + public void setDone(boolean b) { + done.setActive(b); + } + } + ``` 7. Add the logic for creating items when we click the save button. At this point your `Main.java` should be like this: - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.GWT; - import com.google.gwt.event.dom.client.ClickEvent; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.uibinder.client.UiField; - import com.google.gwt.uibinder.client.UiHandler; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; - import com.vaadin.polymer.paper.widget.*; - - public class Main extends Composite { - interface MainUiBinder extends UiBinder { - } - - private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); - - @UiField HTMLPanel content; - - @UiField PaperDialog addItemDialog; - @UiField PaperInput titleInput; - @UiField PaperTextarea descriptionInput; - - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); - } - - @UiHandler("addButton") - protected void onAddButtonClick(ClickEvent e) { - addItemDialog.open(); - } - - @UiHandler("confirmAddButton") - protected void onConfirmAddButtonClick(ClickEvent e) { - if (!titleInput.getValue().isEmpty()) { - addItem(titleInput.getValue(), descriptionInput.getValue()); - // clear text fields - titleInput.setValue(""); - descriptionInput.setValue(""); - } - } - - private void addItem(String title, String description) { - Item item = new Item(); - item.setTitle(title); - item.setDescription(description); - content.add(item); - } - } + ```java + package org.gwtproject.tutorial.client; + + import com.google.gwt.core.client.GWT; + import com.google.gwt.event.dom.client.ClickEvent; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.uibinder.client.UiField; + import com.google.gwt.uibinder.client.UiHandler; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; + import com.vaadin.polymer.paper.widget.*; + + public class Main extends Composite { + interface MainUiBinder extends UiBinder { + } + + private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); + + @UiField HTMLPanel content; + + @UiField PaperDialog addItemDialog; + @UiField PaperInput titleInput; + @UiField PaperTextarea descriptionInput; + + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); + } + + @UiHandler("addButton") + protected void onAddButtonClick(ClickEvent e) { + addItemDialog.open(); + } + + @UiHandler("confirmAddButton") + protected void onConfirmAddButtonClick(ClickEvent e) { + if (!titleInput.getValue().isEmpty()) { + addItem(titleInput.getValue(), descriptionInput.getValue()); + // clear text fields + titleInput.setValue(""); + descriptionInput.setValue(""); + } + } + + private void addItem(String title, String description) { + Item item = new Item(); + item.setTitle(title); + item.setDescription(description); + content.add(item); + } + } + ``` 8. Reload the application @@ -216,109 +227,113 @@ In this section, we'll learn how to add logic to our UI. We'll touch on very bas 9. Add the **Clear All** and **Clear Done** menu item handlers - @UiHandler("menuClearAll") - protected void menuClearAll(ClickEvent e) { - closeMenu(); - content.clear(); - } - - @UiHandler("menuClearDone") - protected void menuClearDone(ClickEvent e) { - closeMenu(); - for (int i = content.getWidgetCount() - 1; i > -1; i--) { - Item item = (Item)content.getWidget(i); - if (item.isDone()) { - content.remove(item); - } - } - } - - private void closeMenu() { - if (drawerPanel.getNarrow()) { - drawerPanel.closeDrawer(); - } - } + ```java + @UiHandler("menuClearAll") + protected void menuClearAll(ClickEvent e) { + closeMenu(); + content.clear(); + } + + @UiHandler("menuClearDone") + protected void menuClearDone(ClickEvent e) { + closeMenu(); + for (int i = content.getWidgetCount() - 1; i > -1; i--) { + Item item = (Item)content.getWidget(i); + if (item.isDone()) { + content.remove(item); + } + } + } + + private void closeMenu() { + if (drawerPanel.getNarrow()) { + drawerPanel.closeDrawer(); + } + } + ``` _**Note**: The closeMenu() method is only useful if the application is viewed on a mobile device, or if your browser window is narrow enough for the side menu to collapse. Hence, we use this method to hide the menu after clicking on any menu item._ 10. The final `Main.java` should look like this - package org.gwtproject.tutorial.client; - - import com.google.gwt.core.client.GWT; - import com.google.gwt.event.dom.client.ClickEvent; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.uibinder.client.UiField; - import com.google.gwt.uibinder.client.UiHandler; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; - import com.vaadin.polymer.paper.widget.PaperDialog; - import com.vaadin.polymer.paper.widget.PaperDrawerPanel; - import com.vaadin.polymer.paper.widget.PaperInput; - import com.vaadin.polymer.paper.widget.PaperTextarea; - - public class Main extends Composite { - interface MainUiBinder extends UiBinder { - } - - private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); - - @UiField PaperDrawerPanel drawerPanel; - @UiField HTMLPanel content; - - @UiField PaperDialog addItemDialog; - @UiField PaperInput titleInput; - @UiField PaperTextarea descriptionInput; - - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); - } - - @UiHandler("addButton") - protected void onAddButtonClick(ClickEvent e) { - addItemDialog.open(); - } - - @UiHandler("confirmAddButton") - protected void onConfirmAddButtonClick(ClickEvent e) { - if (!titleInput.getValue().isEmpty()) { - addItem(titleInput.getValue(), descriptionInput.getValue()); - // clear text fields - titleInput.setValue(""); - descriptionInput.setValue(""); - } - } - - private void addItem(String title, String description) { - Item item = new Item(); - item.setTitle(title); - item.setDescription(description); - content.add(item); - } - - @UiHandler("menuClearAll") - protected void menuClearAll(ClickEvent e) { - closeMenu(); - content.clear(); - } - - private void closeMenu() { - if (drawerPanel.getNarrow()) { - drawerPanel.closeDrawer(); - } - } - - @UiHandler("menuClearDone") - protected void menuClearDone(ClickEvent e) { - closeMenu(); - for (int i = content.getWidgetCount() - 1; i > -1; i--) { - Item item = (Item)content.getWidget(i); - if (item.isDone()) { - content.remove(item); - } - } - } - } + ```java + package org.gwtproject.tutorial.client; + + import com.google.gwt.core.client.GWT; + import com.google.gwt.event.dom.client.ClickEvent; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.uibinder.client.UiField; + import com.google.gwt.uibinder.client.UiHandler; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; + import com.vaadin.polymer.paper.widget.PaperDialog; + import com.vaadin.polymer.paper.widget.PaperDrawerPanel; + import com.vaadin.polymer.paper.widget.PaperInput; + import com.vaadin.polymer.paper.widget.PaperTextarea; + + public class Main extends Composite { + interface MainUiBinder extends UiBinder { + } + + private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); + + @UiField PaperDrawerPanel drawerPanel; + @UiField HTMLPanel content; + + @UiField PaperDialog addItemDialog; + @UiField PaperInput titleInput; + @UiField PaperTextarea descriptionInput; + + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); + } + + @UiHandler("addButton") + protected void onAddButtonClick(ClickEvent e) { + addItemDialog.open(); + } + + @UiHandler("confirmAddButton") + protected void onConfirmAddButtonClick(ClickEvent e) { + if (!titleInput.getValue().isEmpty()) { + addItem(titleInput.getValue(), descriptionInput.getValue()); + // clear text fields + titleInput.setValue(""); + descriptionInput.setValue(""); + } + } + + private void addItem(String title, String description) { + Item item = new Item(); + item.setTitle(title); + item.setDescription(description); + content.add(item); + } + + @UiHandler("menuClearAll") + protected void menuClearAll(ClickEvent e) { + closeMenu(); + content.clear(); + } + + private void closeMenu() { + if (drawerPanel.getNarrow()) { + drawerPanel.closeDrawer(); + } + } + + @UiHandler("menuClearDone") + protected void menuClearDone(ClickEvent e) { + closeMenu(); + for (int i = content.getWidgetCount() - 1; i > -1; i--) { + Item item = (Item)content.getWidget(i); + if (item.isDone()) { + content.remove(item); + } + } + } + } + ``` 11. Reload the application diff --git a/src/main/markdown/doc/latest/polymer-tutorial/widgets-buildui.md b/src/main/markdown/doc/latest/polymer-tutorial/widgets-buildui.md index 2a5798f62..a08e73f54 100644 --- a/src/main/markdown/doc/latest/polymer-tutorial/widgets-buildui.md +++ b/src/main/markdown/doc/latest/polymer-tutorial/widgets-buildui.md @@ -11,64 +11,69 @@ In this chapter we'll build a modern looking UI for the **TodoList** application You can generate these files either by copying the following snippets, or by using the Eclipse GWT plugin. - * `Main.java` + * `Main.java` - package org.gwtproject.tutorial; + ```java + package org.gwtproject.tutorial; - import com.google.gwt.core.client.GWT; - import com.google.gwt.uibinder.client.UiBinder; - import com.google.gwt.user.client.ui.Composite; - import com.google.gwt.user.client.ui.HTMLPanel; + import com.google.gwt.core.client.GWT; + import com.google.gwt.uibinder.client.UiBinder; + import com.google.gwt.user.client.ui.Composite; + import com.google.gwt.user.client.ui.HTMLPanel; - public class Main extends Composite { - interface MainUiBinder extends UiBinder { - } + public class Main extends Composite { + interface MainUiBinder extends UiBinder { + } - private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); + private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class); - public Main() { - initWidget(ourUiBinder.createAndBindUi(this)); - } - } + public Main() { + initWidget(ourUiBinder.createAndBindUi(this)); + } + } + ``` * `Main.ui.xml` - - - - + ```xml + - + + + + ``` 2. Adding **menu items**. Now we can update the `Main.ui.xml` file by adding menu items. - + ```xml + - - - -
      Clear All
      -
      - - -
      Clear Done
      -
      - - -
      Settings
      -
      - - -
      About
      -
      -
      -
      + + + +
      Clear All
      +
      + + +
      Clear Done
      +
      + + +
      Settings
      +
      + + +
      About
      +
      +
      +
      + ``` _**Note**: in this step we have added the necessary imports for Paper and Iron packages._ @@ -76,17 +81,19 @@ In this chapter we'll build a modern looking UI for the **TodoList** application 3. Update the **entry point** to use our new screen. - package org.gwtproject.tutorial; + ```java + package org.gwtproject.tutorial; - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; - public class TodoList implements EntryPoint { + public class TodoList implements EntryPoint { - public void onModuleLoad() { - RootPanel.get().add(new Main()); - } - } + public void onModuleLoad() { + RootPanel.get().add(new Main()); + } + } + ``` 4. Run the application. @@ -100,30 +107,32 @@ In this chapter we'll build a modern looking UI for the **TodoList** application Polymer comes with several icon collections. Before a collection can be used, it has to be imported. In this example we'll be using the Iron set. In the code below, we use the `Polymer.importHref` utility method, and wait for the set to load before we run the application. - package org.gwtproject.tutorial; - - import com.google.gwt.core.client.EntryPoint; - import com.google.gwt.user.client.ui.RootPanel; - import com.vaadin.polymer.Polymer; - import com.vaadin.polymer.elemental.Function; - - public class TodoList implements EntryPoint { - - public void onModuleLoad() { - // We have to load icon sets before run application - Polymer.importHref("iron-icons/iron-icons.html", new Function() { - public Object call(Object arg) { - // The app is executed when all imports succeed. - startApplication(); - return null; - } - }); - } - - private void startApplication() { - RootPanel.get().add(new Main()); - } - } + ```java + package org.gwtproject.tutorial; + + import com.google.gwt.core.client.EntryPoint; + import com.google.gwt.user.client.ui.RootPanel; + import com.vaadin.polymer.Polymer; + import com.vaadin.polymer.elemental.Function; + + public class TodoList implements EntryPoint { + + public void onModuleLoad() { + // We have to load icon sets before run application + Polymer.importHref("iron-icons/iron-icons.html", new Function() { + public Object call(Object arg) { + // The app is executed when all imports succeed. + startApplication(); + return null; + } + }); + } + + private void startApplication() { + RootPanel.get().add(new Main()); + } + } + ``` 2. Reload the application @@ -137,42 +146,43 @@ In this chapter we'll build a modern looking UI for the **TodoList** application * Add `` to each item in the `Main.ui.xml` file. * We need to add a few CSS style properties to the items, so that the ripple effect is constrained within the item area. + ```xml + + + + paper-icon-item { + position: relative; + overflow: hidden; + } + - - - - paper-icon-item { - position: relative; - overflow: hidden; - } - - - - - -
      Clear All
      - -
      - - -
      Clear Done
      - -
      - - -
      Settings
      - -
      - - -
      About
      - -
      -
      -
      + + + +
      Clear All
      + +
      + + +
      Clear Done
      + +
      + + +
      Settings
      + +
      + + +
      About
      + +
      +
      +
      + ``` 4. Reload the application to see the ripple effect in action. @@ -184,63 +194,66 @@ In this chapter we'll build a modern looking UI for the **TodoList** application The Paper elements collection includes a responsive drawer panel. It's a layout component that can be used in modern applications to make sure they behave nicely on both desktop and mobile devices. For more information, check out the paper-drawer-panel [demo](https://elements.polymer-project.org/elements/paper-drawer-panel?view=demo:demo/index.html). - + ```xml + - - paper-icon-item { - position: relative; - overflow: hidden; - } - + + paper-icon-item { + position: relative; + overflow: hidden; + } + - - -
      - - - - -
      Clear All
      - -
      - - -
      Clear Done
      - -
      - - -
      Settings
      - -
      - - -
      About
      - -
      -
      -
      -
      - - - - Todo List - - -
      -
      -
      -
      + + +
      + + + + +
      Clear All
      + +
      + + +
      Clear Done
      + +
      + + +
      Settings
      + +
      + + +
      About
      + +
      +
      +
      +
      + + + + Todo List + + +
      +
      +
      +
      + ``` 2. Add the *content panel* * Add a container for our todo items. - - + + ```xml + ...
      @@ -257,6 +270,7 @@ In this chapter we'll build a modern looking UI for the **TodoList** application
      ...
      + ``` 3. Reload the application @@ -271,35 +285,37 @@ When using Polymer widgets you can use GWT [GSS](https://www.gwtproject.org/doc/ - Change color of the toolbar, style the header text and the content panel: - - .toolbar { - background: #4285f4 !important; - } - .header { - font-size: 200%; - margin-left: 50px; - background: #4285f4 !important; - } - .content { - padding: 15px; - } - ... - - - ... -
      - - - - Todo List - - - -
      - ... -
      + ```xml + + .toolbar { + background: #4285f4 !important; + } + .header { + font-size: 200%; + margin-left: 50px; + background: #4285f4 !important; + } + .content { + padding: 15px; + } + ... + + + ... +
      + + + + Todo List + + + +
      + ... +
      + ``` _**Note**: the `vertical`, `center-justified` and `layout` classes are provided by Polymer._ @@ -315,24 +331,26 @@ Another caveat is that GWT defers `CssResource` loading, so in certain circumsta Material Design applications use the characteristic floating button for the main action. In the Paper elements collection, this button is called [paper-fab][1]. - + ```xml + + ... + + + +
      ... - - - -
      - ... - -
      -
      + +
      +
      + ``` _**Tip**: In order to make Polymer process your style block add the `is="custom-style"` attribute._ @@ -344,79 +362,81 @@ _**Tip**: Take a look at [paper-fab][1] documentation for available custom styli Finally your `Main.ui.xml` file should look like: - - - - paper-icon-item { - position: relative; - overflow: hidden; - } - .toolbar { - background: #4285f4 !important; - } - .header { - font-size: 200%; - margin-left: 50px; - } - .content { - padding: 15px; - } - - - - - -
      - - - - -
      Clear All
      - -
      - - -
      Clear Done
      - -
      - - -
      Settings
      - -
      - - -
      About
      - -
      -
      -
      -
      - - - - Todo List - - - - -
      -
      -
      -
      +```xml + + + + paper-icon-item { + position: relative; + overflow: hidden; + } + .toolbar { + background: #4285f4 !important; + } + .header { + font-size: 200%; + margin-left: 50px; + } + .content { + padding: 15px; + } + + + + + +
      + + + + +
      Clear All
      + +
      + + +
      Clear Done
      + +
      + + +
      Settings
      + +
      + + +
      About
      + +
      +
      +
      +
      + + + + Todo List + + + + +
      +
      +
      +
      +``` If everything is OK, after reloading your app should look like this: diff --git a/src/main/markdown/doc/latest/tutorial/JSON.md b/src/main/markdown/doc/latest/tutorial/JSON.md index 3be7d6f3f..4f4077963 100644 --- a/src/main/markdown/doc/latest/tutorial/JSON.md +++ b/src/main/markdown/doc/latest/tutorial/JSON.md @@ -22,7 +22,7 @@ JSON is a universal, language-independent format for data. In this way, it's sim When you encode the stock data for StockWatcher in JSON format, it will look something like this (but the whitespace will be stripped out). -``` +```json [ { "symbol": "ABC", @@ -48,7 +48,7 @@ When you encode the stock data for StockWatcher in JSON format, it will look som In the original StockWatcher implementation, you created a StockPrice class and used the refreshWatchList method to generate random stock data and then call the updateTable method to populate StockWatcher's flex table. -``` +```java /** * Generate random stock prices. */ @@ -85,7 +85,7 @@ To serve up hypothetical stock quotes in JSON format, you'll create a servlet. T * Eclipse will create a package for the server-side code and a stub for the JsonStockData class. 3. Replace the stub with the following code. -``` +```java package com.google.gwt.sample.stockwatcher.server; import java.io.IOException; @@ -158,7 +158,7 @@ Because you've mapped the StockPriceService to "stockPrices" and the module rena 1. Edit the web application deployment descriptor (StockWatcher/war/WEB-INF/web.xml). * Since the greetServlet is no longer needed, its definition can be removed. -``` +```xml ` tags and specify the HTTP module. -``` +```xml ``` 2. * Open StockWatcher.java and include the following import declarations. Declare the imports for the following Java types. -``` +```java import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestCallback; @@ -420,7 +420,7 @@ The RequestCallback interface is analogous to the AsyncCallback interface in GWT 1. Make the HTTP request and parse the JSON response. * In the refreshWatchList method, replace the TODO comments with the following code . - ``` + ```java // Send request to server and catch any errors. RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url); @@ -444,14 +444,14 @@ The RequestCallback interface is analogous to the AsyncCallback interface in GWT } ``` - * This is where we use `JsonUtils.safeEval()` to convert the JSON string into JavaScript objects. + * This is where we use `JsonUtils.safeEval()` to convert the JSON string into JavaScript objects. 2. You receive two compile errors which you will resolve in a minute. #### Modify the updateTable method To fix the compile errors, modify the updateTable method. - +
      • Change: StockPrice[] prices To: JsArray prices
      • Change: prices.length @@ -463,21 +463,21 @@ To fix the compile errors, modify the updateTable method. 1. * Replace the existing update updateTable(StockPrice[]) method with the following code. -``` +```java updateTable(JsArray prices) ``` * Eclipse flags JsArray. 2. Declare the import. -``` +```java import com.google.gwt.core.client.JsArray; ``` 4. Make a corresponding change in the updateTable(StockPrice price) method. * Change the reference to the StockPrice class to StockData class. -``` +```java private void updateTable(StockData price) { // Make sure the stock is still in the stock table. if (!stocks.contains(price.getSymbol())) { @@ -513,7 +513,7 @@ If something breaks along the way (for example, if the server is offline, or the 3. If the error is corrected, hide the Label widget. * In the updateTable(JsArray prices) method, clear any error messages. -``` +```java private void updateTable(JsArray prices) { for (int i=0; i < prices.length(); i++) { updateTable(prices.get(i)); @@ -535,7 +535,7 @@ In order to display the error, you will need a new UI component; you'll implemen 1. Define a style for the error message so that it will attract the user's attention. * In StockWatcher.css, create a style rule that applies to any element with a class attribute of errorMessage. -``` +```css .negativeChange { color: red; } @@ -548,7 +548,7 @@ In order to display the error, you will need a new UI component; you'll implemen 2. To hold the text of the error message, add a Label widget. * In StockWatcher.java, add the following instance field. -``` +```java private ArrayList stocks = new ArrayList(); private Label errorMsgLabel = new Label(); ``` diff --git a/src/main/markdown/doc/latest/tutorial/JSONphp.md b/src/main/markdown/doc/latest/tutorial/JSONphp.md index 9e0a5fb45..ef38131ec 100644 --- a/src/main/markdown/doc/latest/tutorial/JSONphp.md +++ b/src/main/markdown/doc/latest/tutorial/JSONphp.md @@ -8,7 +8,7 @@ If you have a web server (Apache, IIS, etc.) installed locally and PHP installed * From the Eclipse menu bar, select File > New > File. * In the New File window, enter the file name `stockPrices.php` -``` +```php + ``` ## Invoking the service from the client @@ -274,7 +281,7 @@ To add an AsyncCallback parameter to all of our service methods, you must define 1. In the client subpackage, create an interface and name it StockPriceServiceAsync. 2. Replace the stub with following code. -``` +```java package com.google.gwt.sample.stockwatcher.client; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -303,8 +310,10 @@ The AsyncCallback object contains two methods, one of which is called depending In the StockWatcher class, create an instance of the service proxy class by calling GWT.create(Class). - private ArrayList stocks = new ArrayList(); - private StockPriceServiceAsync stockPriceSvc = GWT.create(StockPriceService.class); + ```java + private ArrayList stocks = new ArrayList(); + private StockPriceServiceAsync stockPriceSvc = GWT.create(StockPriceService.class); + ``` Eclipse flags GWT. @@ -312,35 +321,37 @@ The AsyncCallback object contains two methods, one of which is called depending Replace the existing refreshWatchList method with the following code. - private void refreshWatchList() { - // Initialize the service proxy. - if (stockPriceSvc == null) { - stockPriceSvc = GWT.create(StockPriceService.class); - } - - // Set up the callback object. - AsyncCallback callback = new AsyncCallback() { - public void onFailure(Throwable caught) { - // TODO: Do something with errors. - } + ```java + private void refreshWatchList() { + // Initialize the service proxy. + if (stockPriceSvc == null) { + stockPriceSvc = GWT.create(StockPriceService.class); + } - public void onSuccess(StockPrice[] result) { - updateTable(result); - } - }; + // Set up the callback object. + AsyncCallback callback = new AsyncCallback() { + public void onFailure(Throwable caught) { + // TODO: Do something with errors. + } - // Make the call to the stock price service. - stockPriceSvc.getPrices(stocks.toArray(new String[0]), callback); + public void onSuccess(StockPrice[] result) { + updateTable(result); } + }; + // Make the call to the stock price service. + stockPriceSvc.getPrices(stocks.toArray(new String[0]), callback); + } + ``` + Eclipse flags AsyncCallback. 3. Include the import declarations. -``` -import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; -``` + ```java + import com.google.gwt.core.client.GWT; + import com.google.gwt.user.client.rpc.AsyncCallback; + ``` ### Test the Remote Procedure Call @@ -349,7 +360,7 @@ At this point, you've created a service and pointed to it in the module XML file 1. Launch StockWatcher in development mode using the Eclipse debugger. 2. Examine the error log in the Development Shell window. -``` +```text [ERROR] Type 'com.google.gwt.sample.stockwatcher.client.StockPrice' was not serializable and has no concrete serializable subtypes @@ -386,7 +397,7 @@ Based on the requirements for serialization, what do you need to do to make the Because all its instance fields are primitive types, all you need to do in this case is implement the Serializable or IsSerializable interface. -``` +```java package com.google.gwt.sample.stockwatcher.client; import java.io.Serializable; @@ -439,27 +450,27 @@ To learn how to handle errors in RPC, you will throw an error when the user adds * Eclipse creates a stub DelistedException class. 7. Replace the stub with the following code. -``` -package com.google.gwt.sample.stockwatcher.client; - -import java.io.Serializable; - -public class DelistedException extends Exception implements Serializable { - - private String symbol; - - public DelistedException() { - } - - public DelistedException(String symbol) { - this.symbol = symbol; - } - - public String getSymbol() { - return this.symbol; - } -} -``` + ```java + package com.google.gwt.sample.stockwatcher.client; + + import java.io.Serializable; + + public class DelistedException extends Exception implements Serializable { + + private String symbol; + + public DelistedException() { + } + + public DelistedException(String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return this.symbol; + } + } + ``` ##### Update the stock price service interface: StockPriceService @@ -467,7 +478,7 @@ public class DelistedException extends Exception implements Serializable { In StockPriceService.java, make the changes highlighted below. -``` +```java package com.google.gwt.sample.stockwatcher.client; import com.google.gwt.user.client.rpc.RemoteService; @@ -491,7 +502,7 @@ You need to make two changes to the service implementation (StockPriceServiceImp * For the sake of this example, keep it simple and only throw the exception when the stock symbol ERR is added to the watch list. 3. This listing shows the completed StockPriceServiceImpl class. -``` +```java import com.google.gwt.sample.stockwatcher.client.DelistedException; ... @@ -524,31 +535,35 @@ In order to display the error, you will need a new UI component. First think a m So, to display any messages about failing to retrieve stock data, you'll implement a Label widget. -1. Define a style for the error message so that it will attract the user's attention. - - Serializing StockPrice +1. Define a style for the error message so that it will attract the user's attention. + Serializing StockPrice rule that applies to any element with a class attribute of errorMessage. - .negativeChange { - color: red; - } - - .errorMessage { - color: red; - } + ```css + .negativeChange { + color: red; + } + + .errorMessage { + color: red; + } + ``` 2. To hold the text of the error message, add a Label widget. In StockWatcher.java, add the following instance field. - private StockPriceServiceAsync stockPriceSvc = GWT.create(StockPriceService.class); - private Label errorMsgLabel = new Label(); + ```java + private StockPriceServiceAsync stockPriceSvc = GWT.create(StockPriceService.class); + private Label errorMsgLabel = new Label(); + ``` 3. Initialize the errorMsgLabel when StockWatcher launches. * In the onModuleLoad method, add a secondary class attribute to errorMsgLabel and do not display it when StockWatcher loads. * Add the error message to the Main panel above the stocksFlexTable. + ```java // Assemble Add Stock panel. addPanel.add(newSymbolTextBox); addPanel.add(addButton); @@ -562,6 +577,7 @@ rule that applies to any element with a class attribute of errorMessage. mainPanel.add(stocksFlexTable); mainPanel.add(addPanel); mainPanel.add(lastUpdatedLabel); + ``` #### Handling the error @@ -572,6 +588,7 @@ You will also want to hide the error message if the error is corrected (for exam 1. Specify the action to take if the callback fails. * In StockWatcher.java, in the refreshWatchList method, fill in the onFailure method as follows. + ```java public void onFailure(Throwable caught) { // If the stock code is in the list of delisted codes, display an error message. String details = caught.getMessage(); @@ -582,10 +599,12 @@ You will also want to hide the error message if the error is corrected (for exam errorMsgLabel.setText("Error: " + details); errorMsgLabel.setVisible(true); } + ``` 2. If the error is corrected, hide the error message widget. * In the updateTable(StockPrice[] prices) method, clear any errors. + ```java private void updateTable(StockPrice[] prices) { for (int i=0; i < prices.length; i++) { updateTable(prices[i]); @@ -598,6 +617,7 @@ You will also want to hide the error message if the error is corrected (for exam // Clear any errors. errorMsgLabel.setVisible(false); } + ``` ### Test Exception Handling in RPC diff --git a/src/main/markdown/doc/latest/tutorial/Xsite.md b/src/main/markdown/doc/latest/tutorial/Xsite.md index 90f4c83a5..68ad15a14 100644 --- a/src/main/markdown/doc/latest/tutorial/Xsite.md +++ b/src/main/markdown/doc/latest/tutorial/Xsite.md @@ -92,7 +92,7 @@ The web server will then wrap the JSON response in a call to that function. This technique is called JSON with Padding (JSONP). When the browser finishes downloading the new contents of the ` - - -

        StockWatcher

        -
        - - - + ```html + + + + + + StockWatcher + + + +

        StockWatcher

        +
        + + + ``` #### Automatic Resource Inclusion Like images, CSS files are static resources that are stored in the public directory and referenced from the HTML host page. You can associate a style sheet with your application either of two ways. @@ -92,12 +94,14 @@ Change the theme from Standard to Dark. 2. Uncomment the line referencing the Dark theme. * Eclipse shortcut: Source > Toggle Comment. - - - - - - + ```xml + + + + + + ``` 3. Test the change. * Save your changes to the StockWatcher.gwt.xml file. @@ -163,18 +167,19 @@ When you created the StockWatcher application, webAppCreator generated the appli 2. For any HTML element with the class attribute of watchListHeader, set the color and text properties. * Replace the contents of StockWatcher.css with the following style rules. - /* Formatting specific to the StockWatcher application */ - body { - padding: 10px; - } + ```css + /* Formatting specific to the StockWatcher application */ + body { + padding: 10px; + } - /* stock list header row */ - .watchListHeader { - background-color: #2062B8; - color: white; - font-style: italic; - } - + /* stock list header row */ + .watchListHeader { + background-color: #2062B8; + color: white; + font-style: italic; + } + ``` 3. Save your changes to StockWatcher.css. ### Applying the style with the addStyleName method @@ -186,15 +191,17 @@ However, GWT elements are created dynamically at runtime. So you'll set the HTML 1. In StockWatcher.java, in the onModuleLoad method, add a secondary style to the header row in the stock table. - public void onModuleLoad() { - // Create table for stock data. - stocksFlexTable.setText(0, 0, "Symbol"); - stocksFlexTable.setText(0, 1, "Price"); - stocksFlexTable.setText(0, 2, "Change"); - stocksFlexTable.setText(0, 3, "Remove"); - - // Add styles to elements in the stock list table. - stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); + ```java + public void onModuleLoad() { + // Create table for stock data. + stocksFlexTable.setText(0, 0, "Symbol"); + stocksFlexTable.setText(0, 1, "Price"); + stocksFlexTable.setText(0, 2, "Change"); + stocksFlexTable.setText(0, 3, "Remove"); + + // Add styles to elements in the stock list table. + stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); + ``` 2. Save your changes to StockWatcher.java and then press Refresh in the browser running development mode to see them. * The header row in the flex table displays white italic headings against a blue background. @@ -213,6 +220,7 @@ Each of the changes we will make by creating a secondary style is outlined below 1. Define the style. * In StockWatcher.css, create a style rule for HTML elements with a class attribute of watchList. + ```css /* stock list header row */ .watchListHeader { background-color: #2062B8; @@ -226,13 +234,14 @@ Each of the changes we will make by creating a secondary style is outlined below padding: 2px; margin-bottom:6px; } - + ``` 2. Apply the style. * In StockWatcher.java, add a secondary class attribute to the stock flex table. - + ```java // Add styles to elements in the stock list table. stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); stocksFlexTable.addStyleName("watchList"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * The stock list table has a silver border. @@ -243,7 +252,8 @@ First, you'll format the text in the stock table's header row, which loads when 1. Define the style. * In StockWatcher.css, create a style rule that will right-align the columns that contain the Price and Change fields. - + + ```css /* stock list flex table */ .watchList { border: 1px solid silver; @@ -256,15 +266,16 @@ First, you'll format the text in the stock table's header row, which loads when text-align: right; width:8em; } - + ``` 2. Apply the style. * In StockWatcher.java, add a secondary class attribute to both the Price and Change fields. - + ```java // Add styles to elements in the stock list table. stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); stocksFlexTable.addStyleName("watchList"); stocksFlexTable.getCellFormatter().addStyleName(0, 1, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(0, 2, "watchListNumericColumn"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * The Price and Change columns have a set width and the text in the header row is right-aligned. @@ -274,6 +285,7 @@ First, you'll format the text in the stock table's header row, which loads when 1. Define the style. * In StockWatcher.css, create a style rule that will center the text in the column that contains the Remove button. + ```css /* stock list Price and Change fields */ .watchListNumericColumn { text-align: right; @@ -284,16 +296,19 @@ First, you'll format the text in the stock table's header row, which loads when .watchListRemoveColumn { text-align: center; } + ``` 2. Apply the style. * In StockWatcher.java, add a secondary class attribute to the Remove field. + ```java // Add styles to elements in the stock list table. stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); stocksFlexTable.addStyleName("watchList"); stocksFlexTable.getCellFormatter().addStyleName(0, 1, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(0, 2, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(0, 3, "watchListRemoveColumn"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * The caption takes up the entire width of the field. You'll be able to see that the buttons are centered in the Remove column after you format the data rows in the next step. @@ -306,6 +321,7 @@ You've formatted the header row of the flex table, which is displayed when Stock 2. Apply the style. * In StockWatcher.java, in the addStock method, add secondary class attribute to the table cells in the Price, Change, and Remove columns. + ```java // Add the stock to the table. int row = stocksFlexTable.getRowCount(); stocks.add(symbol); @@ -313,6 +329,7 @@ You've formatted the header row of the flex table, which is displayed when Stock stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * Add stocks to the list. The Price and Change data is right-aligned. The Remove button is centered. @@ -324,6 +341,7 @@ Add whitespace around the text box and Add button in the Add Stock panel. 1. Define the style. * In StockWatcher.css, create a style rule to widen the margins around the Add Stock panel. + ```css /* stock list Remove column */ .watchListRemoveColumn { text-align: center; @@ -333,14 +351,17 @@ Add whitespace around the text box and Add button in the Add Stock panel. .addPanel { margin: 10px 0px 15px 0px; } + ``` 2. Apply the style. * In StockWatcher.java, in the onModuleLoad method add a secondary class attribute to the addPanel. + ```java // Assemble Add Stock panel. addPanel.add(newSymbolTextBox); addPanel.add(addStockButton); addPanel.addStyleName("addPanel"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * The margin between the stock table and the Add Stock panel has increased. @@ -457,29 +478,34 @@ For StockWatcher, you want your style change to apply only to the Remove button. To do this, you'll use the addStyleDependentName method instead of the addStyleName method. 1. Define the style rule. - - /* Add Stock panel */ - .addPanel { - margin: 10px 0px 15px 0px; - } - - /* stock list, the Remove button */ - .gwt-Button-remove { - width: 50px; - } + ```css + /* Add Stock panel */ + .addPanel { + margin: 10px 0px 15px 0px; + } + + /* stock list, the Remove button */ + .gwt-Button-remove { + width: 50px; + } + ``` 2. Apply the style. * In StockWatcher.java, use addStyleDependentName to add a secondary, dependent class attribute to the Remove button. - - // Add a button to remove this stock from the table. - Button removeStockButton = new Button("x"); - removeStockButton.addStyleDependentName("remove"); + + ```java + // Add a button to remove this stock from the table. + Button removeStockButton = new Button("x"); + removeStockButton.addStyleDependentName("remove"); + ``` 3. Save your changes and then press Refresh in the browser running development mode to see them. * The Remove button is wider than it is tall. The Add button is unaffected by this change. 4. Now the resulting generated HTML has two class attributes. - + ```html + + ``` ## Updating styles dynamically @@ -490,35 +516,38 @@ You've already applied an HTML class attribute to the cell element to right-alig 1. Define the style. * In StockWatcher.css, add these style rules. - /* stock list, the Remove button */ - .gwt-Button-remove { - width: 50px; - } + ```css + /* stock list, the Remove button */ + .gwt-Button-remove { + width: 50px; + } - /* Dynamic color changes for the Change field */ - .noChange { - color: black; - } + /* Dynamic color changes for the Change field */ + .noChange { + color: black; + } - .positiveChange { - color: green; - } + .positiveChange { + color: green; + } - .negativeChange { - color: red; - } - + .negativeChange { + color: red; + } + ``` 2. Insert a Label widget in a table cell. * In StockWatcher.java, in the addStock method, create a Label widget for every cell in column 2. - // Add the stock to the table. - int row = stocksFlexTable.getRowCount(); - stocks.add(symbol); - stocksFlexTable.setText(row, 0, symbol); - stocksFlexTable.setWidget(row, 2, new Label()); - stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn"); - stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn"); - stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn"); + ```java + // Add the stock to the table. + int row = stocksFlexTable.getRowCount(); + stocks.add(symbol); + stocksFlexTable.setText(row, 0, symbol); + stocksFlexTable.setWidget(row, 2, new Label()); + stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn"); + stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn"); + stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn"); + ``` * Instead of setting the text on the table cells, now you have to set the text for the Label widget. 3. Set text on the changeWidget. @@ -526,28 +555,32 @@ You've already applied an HTML class attribute to the cell element to right-alig * Create an instance of the Label widget and call it changeWidget. * Set the text on changeWidget. - // Populate the Price and Change fields with new data. - stocksFlexTable.setText(row, 1, priceText); - Label changeWidget = (Label)stocksFlexTable.getWidget(row, 2); - changeWidget.setText(changeText + " (" + changePercentText + "%)"); - -4. Change the color of each changeWidget based on its value. - + ```java // Populate the Price and Change fields with new data. stocksFlexTable.setText(row, 1, priceText); Label changeWidget = (Label)stocksFlexTable.getWidget(row, 2); changeWidget.setText(changeText + " (" + changePercentText + "%)"); + ``` - // Change the color of text in the Change field based on its value. - String changeStyleName = "noChange"; - if (price.getChangePercent() < -0.1f) { - changeStyleName = "negativeChange"; - } - else if (price.getChangePercent() > 0.1f) { - changeStyleName = "positiveChange"; - } +4. Change the color of each changeWidget based on its value. + + ```java + // Populate the Price and Change fields with new data. + stocksFlexTable.setText(row, 1, priceText); + Label changeWidget = (Label)stocksFlexTable.getWidget(row, 2); + changeWidget.setText(changeText + " (" + changePercentText + "%)"); + + // Change the color of text in the Change field based on its value. + String changeStyleName = "noChange"; + if (price.getChangePercent() < -0.1f) { + changeStyleName = "negativeChange"; + } + else if (price.getChangePercent() > 0.1f) { + changeStyleName = "positiveChange"; + } - changeWidget.setStyleName(changeStyleName); + changeWidget.setStyleName(changeStyleName); + ``` 5. Save your changes and then press Refresh in the browser running development mode to see them. * The color of the values in the Change field are red, green, or black depending on whether the change was negative, positive, or none. @@ -560,7 +593,8 @@ In GWT, depending on the HTML element, you can set some attributes in the Java c 1. Specify the cellpadding for the stock table. * In StockWatcher.java, in the onModuleLoad method, add the setCellPadding method. - + + ```java public void onModuleLoad() { // Create table for stock data. stocksFlexTable.setText(0, 0, "Symbol"); @@ -570,6 +604,7 @@ In GWT, depending on the HTML element, you can set some attributes in the Java c // Add styles to elements in the stock list table. stocksFlexTable.setCellPadding(6); + ``` 2. Save your changes and then press Refresh in the browser running development mode to see them. @@ -584,29 +619,34 @@ To include static images in the application. 1. Create an directory to hold the image files associated with this application. * In the war directory, create an images directory. - StockWatcher/war/images + ```text + StockWatcher/war/images + ``` 2. From this page, copy the image of the logo and paste it into the images directory. - StockWatcher/war/images/GoogleCode.png + ```text + StockWatcher/war/images/GoogleCode.png + ``` 3. In StockWatcher.html, insert an img tag pointing to the logo file. - - - - - - StockWatcher - - - - -

        StockWatcher

        -
        - - - + ```html + + + + + + StockWatcher + + + + +

        StockWatcher

        +
        + + + ``` **Note:** HTML comments have been omitted for brevity. 4. Save your changes and then press Refresh in the browser running development mode to see them. diff --git a/src/main/markdown/gettingstarted-v2.md b/src/main/markdown/gettingstarted-v2.md index bca99bf24..d3b06e7c0 100644 --- a/src/main/markdown/gettingstarted-v2.md +++ b/src/main/markdown/gettingstarted-v2.md @@ -38,7 +38,7 @@ and add both to the path. Open a terminal and choose the directory you like to generate the project into. Generate a new project using: -``` +```shell mvn archetype:generate \ -DarchetypeGroupId=net.ltgt.gwt.archetypes \ -DarchetypeVersion=LATEST \ @@ -55,7 +55,7 @@ The archetype will request values for: After entering the parameter above, the terminal shows something like that: -``` +```text [INFO] Using property: module = App Define value for property 'groupId': com.mycompany.mywebapp Define value for property 'artifactId': mywebapp @@ -76,7 +76,7 @@ Enter **Y** to continue. Now, the new project will be generated and you see the following messages: -``` +```text [INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Archetype: modular-webapp:LATEST [INFO] ---------------------------------------------------------------------------- @@ -107,7 +107,7 @@ Switch to the generated directory by entering `cd mywebapp`. Listing of the directory (**Windows**: dir, **Mac and Linux**: ls -la), shows: -``` +```text drwxr-xr-x@ 6 gwt-user staff 192 Dec 17 17:38 . drwx------@ 50 gwt-user staff 1600 Dec 17 17:38 .. drwxr-xr-x@ 4 gwt-user staff 128 Dec 17 17:38 mywebapp-client @@ -120,19 +120,19 @@ drwxr-xr-x@ 4 gwt-user staff 128 Dec 17 17:38 mywebapp-shared To start the code server, run the following command: -``` +```shell mvn gwt:codeserver -pl *-client -am ``` and entering the following command in another terminal window to start the server: -``` +```shell mvn jetty:run -pl *-server -am -Denv=dev ``` Now, switch to your preferred browser (we suggest using: Chrome, FireFox or Opera) and enter: -``` +```text http://localhost:8080 ``` @@ -147,13 +147,13 @@ The source code is located in the `mywebapp-client/src/main/java/com/mycompany/m Look inside `App.java`. Line 42 constructs the "Send" button. -``` +```java final Button sendButton = new Button("Send"); ``` Change the text from "Send" to "Send to Server". -``` +```java final Button sendButton = new Button("Send to Server"); ``` @@ -175,7 +175,7 @@ The execution will stop at line 94. The stacktrace is visible, the content of th To run the application as JavaScript in what GWT calls "production mode", create the application by executing: -``` +```shell mvn clean package ``` diff --git a/src/main/markdown/gettingstarted.md b/src/main/markdown/gettingstarted.md index 97f0b0ea0..c823bd5c7 100644 --- a/src/main/markdown/gettingstarted.md +++ b/src/main/markdown/gettingstarted.md @@ -49,7 +49,7 @@ $JDK_HOME environment variable with export JDK_HOME="/Library/Java/Home" On Windows, extract the files from the compressed folder `gwt-2.10.0.zip`. On Mac or Linux, you can unpack the package with a command like: -``` +```shell unzip gwt-2.10.0.zip ``` @@ -64,7 +64,7 @@ You can create a new demo application in a new MyWebApp directory by running `we * **Windows** -``` +```shell cd gwt-2.10.0 webAppCreator -out MyWebApp com.mycompany.mywebapp.MyWebApp @@ -72,7 +72,7 @@ webAppCreator -out MyWebApp com.mycompany.mywebapp.MyWebApp * **Mac or Linux** - you may need to make the script executable: -``` +```shell cd gwt-2.10.0 chmod u+x webAppCreator @@ -90,7 +90,7 @@ script also generates an Ant build script `MyWebApp/build.xml`. To run your newly created application in development mode: -``` +```shell cd MyWebApp/ ant devmode @@ -118,13 +118,13 @@ the project above. You'll see two packages, Look inside `com/mycompany/mywebapp/client/MyWebApp.java`. Line 41 constructs the "Send" button. -``` +```java final Button sendButton = new Button("Send"); ``` Change the text from "Send" to "Send to Server". -``` +```java final Button sendButton = new Button("Send to Server"); ``` @@ -134,7 +134,7 @@ Now, save the file and simply click "Refresh" in your browser to see your change To run the application as JavaScript in what GWT calls "production mode", compile the application by executing: -``` +```shell ant build ``` diff --git a/src/main/markdown/makinggwtbetter.md b/src/main/markdown/makinggwtbetter.md index a472840ee..839691cb0 100644 --- a/src/main/markdown/makinggwtbetter.md +++ b/src/main/markdown/makinggwtbetter.md @@ -269,7 +269,7 @@ statements should follow, each block separated by a blank line. Next is the class or interface declaration. In the Javadoc comments, describe what the class or interface does. -``` +```java /* * Copyright 2006 Google Inc. * @@ -326,7 +326,7 @@ All methods should be sorted alphabetically. Sorting is optional but recommended for fields. For example, the following class excerpt is correctly sorted: -``` +```java public abstract class Foo { // Type declarations. public class FooBaz { @@ -414,14 +414,14 @@ We use 4-space indents after line wraps, including function calls and assignments. For example, this is correct (4 spaces after the newline): -``` +```java Instrument i = new Instrument(); ``` and this is not correct (2 spaces after the newline): -``` +```java Instrument i = new Instrument(); ``` @@ -496,7 +496,7 @@ Tests for Java classes should be placed in a parallel source tree under `test` and the test class name should be suffixed with `Test`. For example: -``` +```text src/com/google/gwt/core/client/EntryPoint.java test/com/google/gwt/core/client/EntryPointTest.java ``` diff --git a/src/main/markdown/release-notes.md b/src/main/markdown/release-notes.md index 3680326ef..863791e20 100644 --- a/src/main/markdown/release-notes.md +++ b/src/main/markdown/release-notes.md @@ -242,7 +242,7 @@ by `window.onerror`. This may potentially be a breaking change if there were misbehaving scripts on the page. To disable this functionality, set the property `gwt.uncaughtexceptionhandler.windowonerror` to `IGNORE`: -``` +```xml ``` @@ -391,7 +391,7 @@ prefered supertype of any JS type, including primitives. - Allow `@JsOverlay` on effectively final methods. - Split JsInterop annotations into their own JAR when deploying to Maven: -``` +```xml com.google.jsinterop jsinterop-annotations @@ -1748,7 +1748,7 @@ Design](http://code.google.com/p/google-web-toolkit/wiki/LayoutDesign) on the wi and [TabLayoutPanel](/javadoc/latest/com/google/gwt/user/client/ui/TabLayoutPanel.html). * UiBinder now directly supports `LayoutPanel`. For example: -``` +```xml left-width right-width diff --git a/src/main/markdown/usingeclipse.md b/src/main/markdown/usingeclipse.md index ab60a8ddd..01faf147f 100644 --- a/src/main/markdown/usingeclipse.md +++ b/src/main/markdown/usingeclipse.md @@ -82,13 +82,13 @@ Look inside the file in the client package. Line 40 constructs the send button. -``` +```java final Button sendButton = new Button("Send"); ``` Change the text from "Send" to "Send to Server". -``` +```java final Button sendButton = new Button("Send to Server"); ``` diff --git a/src/main/markdown/versions.md b/src/main/markdown/versions.md index 64a58f4f5..758ce7542 100644 --- a/src/main/markdown/versions.md +++ b/src/main/markdown/versions.md @@ -809,7 +809,6 @@ Build 1.4.10 - May 29, 2007 - [Release notes](release-notes.html#Release_Notes_1 Mac OS X 10.4 [gwt-mac-1.4.10.tar.gz](https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/google-web-toolkit/gwt-mac-1.4.10.tar.gz) - 22 MB 8fdaef4ab8b13cfad25063e8987877d9 @@ -817,7 +816,6 @@ Build 1.4.10 - May 29, 2007 - [Release notes](release-notes.html#Release_Notes_1 Linux (i386 GTK2)* [gwt-linux-1.4.10.tar.bz2](https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/google-web-toolkit/gwt-linux-1.4.10.tar.bz2) 32 MB - 8672a81eb0f82091ab0ea01e3f92c2c3 diff --git a/src/main/site/javadoc/latest/legal/jquery.md b/src/main/site/javadoc/latest/legal/jquery.md index d468b3183..8caab8c60 100644 --- a/src/main/site/javadoc/latest/legal/jquery.md +++ b/src/main/site/javadoc/latest/legal/jquery.md @@ -1,7 +1,8 @@ ## jQuery v3.6.1 ### jQuery License -``` + +```text jQuery v 3.6.1 Copyright OpenJS Foundation and other contributors, https://openjsf.org/ diff --git a/src/main/site/javadoc/latest/legal/jqueryUI.md b/src/main/site/javadoc/latest/legal/jqueryUI.md index 8bda9d7a8..4fa33adf3 100644 --- a/src/main/site/javadoc/latest/legal/jqueryUI.md +++ b/src/main/site/javadoc/latest/legal/jqueryUI.md @@ -1,7 +1,8 @@ ## jQuery UI v1.13.2 ### jQuery UI License -``` + +```text Copyright jQuery Foundation and other contributors, https://jquery.org/ This software consists of voluntary contributions made by many From a9050c0c0252fba47a0bebbad5627ddde5a59eb3 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sat, 31 Aug 2024 17:43:14 +0200 Subject: [PATCH 5/7] Fix indentation to avoid extra code blocks --- src/main/markdown/doc/latest/tutorial/JSON.md | 33 ++++++------ src/main/markdown/examples.md | 51 +++++++++---------- src/main/markdown/release-notes.md | 12 ++--- 3 files changed, 46 insertions(+), 50 deletions(-) diff --git a/src/main/markdown/doc/latest/tutorial/JSON.md b/src/main/markdown/doc/latest/tutorial/JSON.md index 4f4077963..9ff5f85a1 100644 --- a/src/main/markdown/doc/latest/tutorial/JSON.md +++ b/src/main/markdown/doc/latest/tutorial/JSON.md @@ -497,16 +497,16 @@ If something breaks along the way (for example, if the server is offline, or the 1. Clear the compiler error by creating a stub method in the StockWatcher class. * Set the text for the error message and make the Label widget visible. -``` - /** - * If can't get JSON, display error message. - * @param error - */ - private void displayError(String error) { - errorMsgLabel.setText("Error: " + error); - errorMsgLabel.setVisible(true); - } -``` + ```java + /** + * If can't get JSON, display error message. + * @param error + */ + private void displayError(String error) { + errorMsgLabel.setText("Error: " + error); + errorMsgLabel.setVisible(true); + } + ``` 2. Eclipse flags errorMsgLabel. * Ignore the compile errors for a moment; you'll implement a Label widget to display the error text in the next step. @@ -557,7 +557,7 @@ private Label errorMsgLabel = new Label(); * In the onModuleLoad method, add a secondary class attribute to errorMsgLabel and do not display it when StockWatcher loads. * Add the error message to the Main panel above the stocksFlexTable. -``` + ```java // Assemble Add Stock panel. addPanel.add(newSymbolTextBox); addPanel.add(addButton); @@ -571,7 +571,7 @@ private Label errorMsgLabel = new Label(); mainPanel.add(stocksFlexTable); mainPanel.add(addPanel); mainPanel.add(lastUpdatedLabel); -``` + ``` ### Test the HTTP request and error handling @@ -579,13 +579,10 @@ private Label errorMsgLabel = new Label(); 2. Enter several stock codes.
        StockWatcher should display Price and Change data for each stock. Rather than being generated from within the program the stock data is coming from you local server in JSON format. 3. Test the HTTP error messages by calling an invalid URL. - * In StockWatcher,java, edit the URL. - * -Change: `private static final String JSON_URL = GWT.getModuleBaseURL() - + "stockPrices?q=";` + * In StockWatcher,java, edit the URL. + * Change: `private static final String JSON_URL = GWT.getModuleBaseURL() + "stockPrices?q=";` - To: `private static final String JSON_URL = GWT.getModuleBaseURL() - + "BADURL?q=";` + To: `private static final String JSON_URL = GWT.getModuleBaseURL() + "BADURL?q=";` 4. Refresh StockWatcher in development mode. 5. Enter a stock code. * StockWatcher displays a red error message. Valid stock code data stops being refreshed. diff --git a/src/main/markdown/examples.md b/src/main/markdown/examples.md index 817514535..ae3c62ab2 100644 --- a/src/main/markdown/examples.md +++ b/src/main/markdown/examples.md @@ -85,37 +85,36 @@ Please note that the applications linked from this page are provided by third-pa
        -
        - Screenshot -
        -
        - -
        A showcase of GWT features with accompanying source code and CSS styles.
        -
        -
        GWT features used:
        - - -
        +
        + Screenshot +
        +
        + +
        A showcase of GWT features with accompanying source code and CSS styles.
        +
        +
        GWT features used:
        + +
        -
        +
        +
        -
        -
        - Screenshot -
        -
        - -
        A replica of the UI of a desktop email application.
        -
        -
        GWT features used:
        - - -
        +
        +
        + Screenshot +
        +
        + +
        A replica of the UI of a desktop email application.
        +
        +
        GWT features used:
        + +
        +
        -
        - The source for these examples as well as others can be found in your GWT distribution under the `samples/` directory. If you haven't downloaded GWT yet, you can download it here. + The source for these examples as well as others can be found in your GWT distribution under the `samples/` directory. If you haven't downloaded GWT yet, you can download it here.
        diff --git a/src/main/markdown/release-notes.md b/src/main/markdown/release-notes.md index f59d29e1c..235145a4c 100644 --- a/src/main/markdown/release-notes.md +++ b/src/main/markdown/release-notes.md @@ -1219,12 +1219,12 @@ r10730 for more details. * The following dependencies have been updated to the following versions: - * Eclipse JDT 3.4.2_r894 - * Guava 10.0.1 - * HTMLUnit 2.9 - * Apache HTTP Client 4.1.2 (for HTMLUnit) - * Apache Commons Lang 2.6 (for HTMLUnit) - * NekoHTML 1.9.15 (for HTMLUnit) + * Eclipse JDT 3.4.2_r894 + * Guava 10.0.1 + * HTMLUnit 2.9 + * Apache HTTP Client 4.1.2 (for HTMLUnit) + * Apache Commons Lang 2.6 (for HTMLUnit) + * NekoHTML 1.9.15 (for HTMLUnit) * json-1.5.jar is now bundled as a part of gwt-dev.jar. streamhtmlparser (rebased) has been removed from gwt-dev.jar and has been bundled as part of gwt-user.jar and gwt-servlet.jar. From 2233f93e44d85a769b93c90b97ed021b700dd3e9 Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sun, 27 Oct 2024 10:14:53 +0100 Subject: [PATCH 6/7] Vertical scrollbar for text code blocks --- src/main/site/assets/less/layout.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/site/assets/less/layout.less b/src/main/site/assets/less/layout.less index 0e814dda4..d86498482 100644 --- a/src/main/site/assets/less/layout.less +++ b/src/main/site/assets/less/layout.less @@ -275,7 +275,7 @@ pre > code { display: block; padding: 10px; margin-bottom: 1em; - + overflow-x: auto; .box-sizing(); } From d7943bbf65a036014bfe874fb3b0434e2c29a92f Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sun, 27 Oct 2024 10:29:57 +0100 Subject: [PATCH 7/7] Simplify less functions --- src/main/site/assets/less/functions.less | 181 +---------------------- src/main/site/assets/less/layout.less | 4 +- src/main/site/assets/less/style.less | 16 +- src/main/site/css/style.min.css | 1 - 4 files changed, 11 insertions(+), 191 deletions(-) delete mode 100644 src/main/site/css/style.min.css diff --git a/src/main/site/assets/less/functions.less b/src/main/site/assets/less/functions.less index d3b024e8c..0325ca977 100644 --- a/src/main/site/assets/less/functions.less +++ b/src/main/site/assets/less/functions.less @@ -5,132 +5,12 @@ More info at: http://lesselements.com --------------------------------------------------- - - Gradient background - - Drop shadow - - Inner shadow - - Rounded - - Border radius - - Opacity - Transition - - Transition duration - Rotation - - Scale - - Translate - Box sizing */ -/* - Gradient background - * - * First color is the background color to use for browsers - * that don't support gradients. The second two colors are - * the start and stop colors, going from bottom to top. - */ - -.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) { - background: @color; - background: -webkit-gradient(linear, - left bottom, - left top, - color-stop(0, @start), - color-stop(1, @stop)); - background: -ms-linear-gradient(bottom, - @start, - @stop); - background: -moz-linear-gradient(center bottom, - @start 0%, - @stop 100%); - background: -o-linear-gradient(@stop, - @start); - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@stop,@start)); -} - -/* - Drop shadow - * - * Adds a box-shadow that is a semi-transparent black. The - * first two values control the x and y axis position, the - * third controls blur (how big the shadow is), and the final - * value is the opacity (0 is fully transparent, 1 is opaque). - */ - -.drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) { - -webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha); - -moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha); - box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha); -} - -/* - Inner shadow - * - * Sets the inner shadow. The first two numbers are the x and y - * coordinates, the third is the blur and the last one is the - * strength of the shadow. - */ - -.inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) { - -webkit-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha); - -moz-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha); - box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha); -} - -/* - Box shadow - */ - -.box-shadow(@arguments) { - -webkit-box-shadow: @arguments; - -moz-box-shadow: @arguments; - box-shadow: @arguments; -} - -/* - Rounded - * - * Sets a border-radius for all 4 corners. If you want to set - * border-radius for individual corners use: .border-radius - */ - -.rounded(@radius: 2px) { - -webkit-border-radius: @radius; - -moz-border-radius: @radius; - border-radius: @radius; -} - -/* - Border radius - * - * Sets a border-radius for each of the 4 corners individually. - * The values go in a clockwise rotation: top right, bottom right, - * bottom left, top left. - */ - -.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) { - -webkit-border-top-right-radius: @topright; - -webkit-border-bottom-right-radius: @bottomright; - -webkit-border-bottom-left-radius: @bottomleft; - -webkit-border-top-left-radius: @topleft; - -moz-border-radius-topright: @topright; - -moz-border-radius-bottomright: @bottomright; - -moz-border-radius-bottomleft: @bottomleft; - -moz-border-radius-topleft: @topleft; - border-top-right-radius: @topright; - border-bottom-right-radius: @bottomright; - border-bottom-left-radius: @bottomleft; - border-top-left-radius: @topleft; - .background-clip(padding-box); -} - -/* - Opacity - * - * Sets the opacity. 0 is fully transparent, 1 is opaque. - */ - -.opacity(@opacity: 0.5) { - -moz-opacity: @opacity; - -khtml-opacity: @opacity; - -webkit-opacity: @opacity; - opacity: @opacity; - @opperc: @opacity * 100; - -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(opacity=@{opperc})"; - filter: ~"alpha(opacity=@{opperc})"; -} - /* - Transition * * Sets the transition duration and effect to use for any @@ -139,63 +19,16 @@ */ .transition(@duration:0.2s, @ease:ease-out) { - -webkit-transition: all @duration @ease; - -moz-transition: all @duration @ease; - -o-transition: all @duration @ease; transition: all @duration @ease; } -/* - Transition duration - * - * Sets a transition-duration (time it takes to do things like - * hover effects). The value provides a time in seconds. - */ - -.transition-duration(@duration: 0.2s) { - -moz-transition-duration: @duration; - -webkit-transition-duration: @duration; - -o-transition-duration: @duration; - transition-duration: @duration; -} - -/* - Transform - */ - -.transform(...) { - -webkit-transform: @arguments; - -moz-transform: @arguments; - -o-transform: @arguments; - -ms-transform: @arguments; - transform: @arguments; -} - /* - Rotation * * Rotates the item by a number of degrees clockwise. */ .rotation(@deg:5deg){ - .transform(rotate(@deg)); -} -/* - Scale - * - * Scales the item by the ratio provided. The example makes the - * item 2 times larger. - */ - -.scale(@ratio:1.5){ - .transform(scale(@ratio)); -} - -/* - Translate - * - * Translates an element using the given coordinates. The values - * are x and y offset coordinates, so the above example moves the - * element right 10 pixels and up 20 pixels. - */ - -.translate(@x:0, @y:0) { - .transform(translate(@x, @y)); + transform: rotate(@deg); } /* - Boox sizing @@ -206,17 +39,5 @@ */ .box-sizing(@sizing: border-box) { - -ms-box-sizing: @sizing; - -moz-box-sizing: @sizing; - -webkit-box-sizing: @sizing; box-sizing: @sizing; } - -/* - Background clip - */ - -.background-clip(@argument: padding-box) { - -moz-background-clip: @argument; - -webkit-background-clip: @argument; - background-clip: @argument; -} \ No newline at end of file diff --git a/src/main/site/assets/less/layout.less b/src/main/site/assets/less/layout.less index d86498482..f377cde82 100644 --- a/src/main/site/assets/less/layout.less +++ b/src/main/site/assets/less/layout.less @@ -83,7 +83,7 @@ h1 { left: -18px; bottom: -20px; - .rounded(10px); + border-radius: 10px; } a { @@ -113,7 +113,7 @@ h2 { left: -18px; bottom: -11px; - .rounded(10px); + border-radius: 10px; } } diff --git a/src/main/site/assets/less/style.less b/src/main/site/assets/less/style.less index ad9431d52..28fcdedb1 100755 --- a/src/main/site/assets/less/style.less +++ b/src/main/site/assets/less/style.less @@ -119,7 +119,7 @@ left: 5px; .transition(); - .opacity(0); + opacity: 0; } span { @@ -159,7 +159,7 @@ font-size: 14px; font-size: 1.4rem; - .rounded(8px); + border-radius: 8px; .transition(); &:hover { @@ -224,7 +224,7 @@ } .logo a::after { - .opacity(1); + opacity: 1; } .sep::after { @@ -428,14 +428,14 @@ nav#nav-mobile { right: 0; z-index: 10000; - .border-radius(0, 0, 5px, 0); + border-bottom-left-radius: 5px; input { display: none; border: 0; padding: 2px 4px; - .border-radius(0, 0, 3px, 0); + border-bottom-left-radius: 3px; @media (@mobile) { display: inline-block; @@ -570,7 +570,7 @@ nav#nav-mobile { top: 8px; left: 0; - .rounded(2px) + border-radius: 2px; } &::before { @@ -680,7 +680,7 @@ nav#nav-mobile { border: 2px solid #000; margin-bottom: 8px; - .rounded(100%); + border-radius: 100%; .transition(); &.active { @@ -710,7 +710,7 @@ nav#nav-mobile { opacity: 1; visibility: visible; - .translate(10px); + transform: translateX(10px); } } diff --git a/src/main/site/css/style.min.css b/src/main/site/css/style.min.css deleted file mode 100644 index dcb5c1265..000000000 --- a/src/main/site/css/style.min.css +++ /dev/null @@ -1 +0,0 @@ -/*! normalize.css v1.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}.mixin-col{border:0 solid rgba(0,0,0,0);float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-moz-background-clip:padding-box!important;-webkit-background-clip:padding-box!important;background-clip:padding-box!important;margin-bottom:0}.col{border:0 solid rgba(0,0,0,0);float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-moz-background-clip:padding-box!important;-webkit-background-clip:padding-box!important;background-clip:padding-box!important;margin-bottom:0}.row.nospace .col{padding:0}.mixin-span_first{margin-left:0}.row.sameh{overflow:hidden;margin-bottom:10px}.row.sameh .col{margin-bottom:-99999px;padding-bottom:99999px}@media screen and (min-width:0) and (max-width:649px){.col{margin-left:1%;padding:0 10px}.col-m1_4,.col-t1_4,.col-1_4{width:25%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-m1_2,.col-t1_2,.col-1_2{width:50%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-m3_4,.col-t3_4,.col-3_4{width:75%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-mfull,.col-tfull,.col-full{margin-left:0;width:98%;margin-left:1%}.col-mhide{display:none}}@media screen and (min-width:650px) and (max-width:959px){.col{margin-left:.5%;padding:0 10px}.row .col:first-child{margin-left:0}.col-t1_8{width:12.5%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t1_4,.col-1_4{width:25%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t3_8,.col-1_3{width:37.5%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t1_2,.col-1_2{width:50%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t5_8,.col-2_3{width:62.5%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t3_4,.col-3_4{width:75%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-t7_8{width:87.5%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-tfull,.col-full{width:100%;border-left-width:2px;border-right-width:2px;padding:0 10px;margin-left:0}.col-thide{display:none}}@media screen and (min-width:960px){.col{margin-left:0;padding:0 5px}.row .col:first-child{margin-left:0}.col-1_12{width:8.33333333%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-1_6{width:16.66666667%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-1_4{width:25%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-1_3{width:33.33333333%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-5_12{width:41.66666667%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-1_2{width:50%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-7_12{width:58.33333333%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-2_3{width:66.66666667%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-3_4{width:75%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-5_6{width:83.33333333%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-11_12{width:91.66666667%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-full{width:100%;border-left-width:20px;border-right-width:20px;padding:0;margin-left:0}.col-hide{display:none}}html{font-size:62.5%;line-height:1.4}@media (max-width:979px){html{font-size:55%}}@media (mobile){html{font-size:51%}}body{font-family:soleil,sans-serif;font-weight:400;font-size:16px;font-size:1.6rem;background-color:#f2f2f2;color:#000;padding:0}.container{margin:0;padding:0 50px 0 330px;max-width:960px;position:relative}.container.full{max-width:100%;padding-right:25px}@media (max-width:979px){.container{padding:0 40px 0 280px;max-width:650px}}@media (max-width:749px){.container{padding:0 2%;width:96%}}.home .container{padding:0 45px 0 285px}h1{font-size:40px;font-size:4rem;font-weight:700;line-height:1em;margin:0 0 1em}h1::after{content:"";background-color:#000;display:block;width:22px;height:3px;position:relative;left:-18px;bottom:-24px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}h2{color:#d6171e;font-size:28px;font-size:2.8rem;margin:1em 0 .9em}h2::after{content:"";background-color:#d6171e;display:block;width:22px;height:3px;position:relative;left:-18px;bottom:-14px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}h3{font-size:18px;font-size:1.8rem;margin:.2em 0 .9em}h4{font-size:16px;font-size:1.6rem;margin:.2em 0 .9em}h4 strong,h4 code{color:#d6171e}html,button,input,select,textarea{color:#222}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}p{line-height:1.4em;margin-bottom:.8em}strong{font-weight:700}em{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}audio,canvas,img,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}ul,ol{list-style-position:outside;margin-left:1.5em;padding-left:0}code{margin-bottom:1em}p>code{background-color:#fff;display:block;padding:10px;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.browsehappy{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{background-color:transparent;border:0;overflow:hidden;*text-indent:-9999px}.ir:before{content:"";display:block;width:0;height:150%}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}.flexnav{-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;-webkit-transform-style:preserve-3d;overflow:hidden;margin:0 auto;width:100%;max-height:0}.flexnav.opacity{opacity:0}.flexnav.flexnav-show{max-height:2000px;opacity:1;-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;transition:all .5s ease-in-out}.flexnav.one-page{position:fixed;top:50px;right:5%;max-width:200px}.flexnav ul{margin:0}.flexnav li{font-size:100%;position:relative;overflow:hidden}.flexnav li a{position:relative;display:block;padding:.96em;z-index:2;overflow:hidden;color:#222;background:#a6a6a2;border-bottom:1px solid rgba(255,255,255,.7);text-decoration:none;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.flexnav li a:hover{padding-left:1.5em}.flexnav li ul{width:100%}.flexnav li ul li{font-size:100%;position:relative;overflow:hidden}.flexnav li ul.flexnav-show li{overflow:visible}.flexnav li ul li a{display:block;background:#b2b2af}.flexnav ul li ul li a{background:#bfbfbc}.flexnav ul li ul li ul li a{background:#cbcbc9}.flexnav .touch-button{position:absolute;z-index:999;top:0;right:0;width:50px;height:46px;display:inline-block;background:#acaca1;background:rgba(0,0,0,.075);text-align:center}.flexnav .touch-button:hover{cursor:pointer}.flexnav .touch-button .navicon{position:relative;top:1.4em;font-size:12px;color:#666}.flexnav .touch-button .navicon::before{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.flexnav .touch-button.active .navicon::before{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}.menu-button{position:relative;display:block;padding:1em;background:0 0;color:#222;cursor:pointer;border-bottom:0;text-align:right}.menu-button i{display:none}.menu-button.one-page{position:fixed;top:0;right:5%;padding-right:45px}.menu-button .touch-button{background:0 0;position:absolute;z-index:999;top:0;right:0;width:50px;height:50px;display:inline-block;text-align:center}.menu-button .touch-button .navicon{font-size:16px;position:relative;top:1em;color:#666}@media all and (min-width:750px){body.one-page{padding-top:70px}.flexnav{overflow:visible}.flexnav.opacity{opacity:1}.flexnav.one-page{top:0;right:auto;max-width:1080px}.flexnav li{position:relative;list-style:none;float:left;display:block;background-color:#a6a6a2;overflow:visible;width:20%}.flexnav li a{border-left:1px solid #acaca1;border-bottom:none}.flexnav li>ul{position:absolute;top:auto;left:0}.flexnav li>ul li{width:100%}.flexnav li ul li>ul{margin-left:100%;top:0}.flexnav li ul li a{border-bottom:none}.flexnav li ul.open{display:block;opacity:1;visibility:visible;z-index:1}.flexnav li ul.open li{overflow:visible;max-height:100px}.flexnav li ul.open ul.open{margin-left:100%;top:0}.menu-button{display:none}}.oldie body.one-page{padding-top:70px}.oldie .flexnav{overflow:visible}.oldie .flexnav.one-page{top:0;right:auto;max-width:1080px}.oldie .flexnav li{position:relative;list-style:none;float:left;display:block;background-color:#a6a6a2;width:20%;min-height:50px;overflow:visible}.oldie .flexnav li:hover>ul{display:block;width:100%;overflow:visible}.oldie .flexnav li:hover>ul li{width:100%;float:none}.oldie .flexnav li a{border-left:1px solid #acaca1;border-bottom:none;overflow:visible}.oldie .flexnav li>ul{background:#acaca1;position:absolute;top:auto;left:0;display:none;z-index:1;overflow:visible}.oldie .flexnav li ul li ul{top:0}.oldie .flexnav li ul li a{border-bottom:none}.oldie .flexnav li ul.open{display:block;width:100%;overflow:visible}.oldie .flexnav li ul.open li{width:100%}.oldie .flexnav li ul.open ul.open{margin-left:100%;top:0;display:block;width:100%;overflow:visible}.oldie .flexnav ul li:hover ul{margin-left:100%;top:0}.oldie .menu-button{display:none}.oldie.ie7 .flexnav li{width:19.9%}#nav{background-color:#dbdbdb;min-height:100%;width:260px;padding:0;border-top:6px solid #d6171e;overflow-x:hidden;position:fixed;top:0;left:0;z-index:9000;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav .wrapper{width:260px}#nav ul{margin:35px 0 0;padding:0}#nav li{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav li a{color:#4d4d4d;text-decoration:none;font-size:15px;font-size:1.5rem;display:inline-block;width:100%;padding:0 35px 4px;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav li a:hover,#nav li a.active{background-color:#c2c2c2}#nav li i{font-size:130%;vertical-align:baseline}#nav li i::before{margin-left:0;margin-right:.5em;position:relative;top:1px}#nav li.logo a{background:url(../img/navLogoBig.png) no-repeat;text-align:center;text-indent:-9999px;display:block;width:160px;height:149px;margin:0 auto 40px}#nav li.logo a::after{content:"";background:url(../img/navLogoSmall.png) no-repeat;display:block;width:24px;height:17px;position:absolute;top:20px;left:8px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;-moz-opacity:0;-khtml-opacity:0;-webkit-opacity:0;opacity:0;-ms-filter:alpha(opacity=0);filter:alpha(opacity=0)}#nav li.sep{margin-bottom:25px;position:relative}#nav li.sep::after{content:"";display:block;width:22px;height:3px;background-color:#c2c2c2;position:absolute;bottom:-14px;left:35px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav li.btn{padding:0 35px;margin-bottom:10px;margin-left:0}#nav li.btn a{background-color:#d6171e;color:#fff;font-size:14px;font-size:1.4rem;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav li.btn a:hover{background-color:#9c1421}#nav #social{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav #social a{color:#fff;text-align:center;font-size:50px;font-size:5rem;display:block;width:100%;height:40px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#nav #social a span{display:none}#nav #cc{color:#9e9d9d;text-align:center;text-decoration:none;font-size:13px;font-size:1.3rem;display:block;width:100%;padding:10px 35px;margin-top:20px;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#nav.closed{width:40px}#nav.closed a{padding-left:14px}@media (max-width:979px){#nav.closed a{padding-left:15px}}#nav.closed li i{margin-left:-3px;padding-right:1em}#nav.closed .logo a::after{-moz-opacity:1;-khtml-opacity:1;-webkit-opacity:1;opacity:1;-ms-filter:alpha(opacity=100);filter:alpha(opacity=100)}#nav.closed .sep::after{left:10px}#nav.closed .btn{margin-left:-32px}#nav.closed #social a{font-size:30px;font-size:3rem;margin-left:-122px;height:30px}@media (max-width:979px){#nav.closed #social a{margin-left:-123px}}@media (max-width:749px){#nav{display:none}}aside#submenu{background-color:#c2c2c2;width:240px;height:100%;padding-top:229px;position:fixed;top:0;left:30px;z-index:8500}@media (max-width:979px){aside#submenu{width:200px}}aside#submenu a{color:#4d4d4d;text-decoration:none;font-size:15px;font-size:1.5rem;display:inline-block;width:100%;padding:6px 25px;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}aside#submenu a:hover{background-color:#f2f2f2}aside#submenu ul{margin:0;padding:0;position:relative}aside#submenu ul ul{padding:0 0 5px;margin-bottom:5px}aside#submenu ul ul::before{content:"\e80e";font-family:icons;display:block;width:10px;height:10px;position:absolute;top:-27px;right:12px}aside#submenu ul ul a{padding-left:50px}aside#submenu ul ul::after{content:"";background-color:#dbdbdb;display:block;width:190px;height:2px;position:relative;bottom:-5px;left:25px}@media (max-width:979px){aside#submenu ul ul::after{width:160px}}@media (max-width:749px){aside#submenu{display:none}}a#logo-mobile{display:none}@media (max-width:749px){a#logo-mobile{background:url(../img/navLogoBig.png) no-repeat;-webkit-background-size:contain;background-size:contain;text-indent:-9999px;display:block;width:80px;height:80px;position:relative;top:14px;left:2.2%}}.menu-button{top:-20px}nav#nav-mobile{display:none}@media (max-width:749px){nav#nav-mobile{display:block;position:relative;top:-22px}}#search{background-color:#d6171e;color:#fff;padding:4px 2px 5px 6px;position:absolute;top:0;right:0;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:5px;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:5px;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:5px;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}#search input{display:none;border:0;padding:2px 4px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:3px;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}@media (max-width:749px){#search input{display:inline-block}}#search button{background-color:#d6171e;color:#fff;font-weight:400;border:0}#search button span{text-indent:-9999px;display:inline-block}#search:hover input{display:inline-block}#content{padding:8em 0 3em}@media (max-width:749px){#content{padding-top:3em}}#content.home{padding:0}#content.home h1{font-size:85px;font-size:8.5rem;margin:0 0 .5em}#content.home h1 span{display:inline-block}#content.home h1 strong{font-size:150px;font-size:15rem;font-weight:800;line-height:.7em;display:block}#content.home h1::after{display:none}#content.home h2{font-size:28px;font-size:2.8rem;text-transform:uppercase;margin:.2em 0 .9em}#content.home h2::after{display:none}#content.home section{padding:5em 0;width:100%}#content.home section.alternate{background-color:#d6171e;color:#fff}#content.home section.alternate h1 strong{color:#000}#content.home section#letsbegin .col-1_4{text-align:center}#content.home section#letsbegin .col-1_4 p{font-size:14px;font-size:1.4rem}@media print{*{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}} \ No newline at end of file