21
I Use This!
Activity Not Available

News

Posted over 10 years ago by [email protected] (Divya Dadlani)
Web Components is an emerging web technology that allows web developers to use custom HTML elements and encapsulation in their applications. Currently, Polymer is the leading web framework that implements this technology. A few members of the Errai ... [More] community have expressed interest in using Polymer elements in their web apps, hence we spent some time creating an early prototype at Errai Tutorial - Web Components. In this blog post, I will outline the steps needed to use Polymer components with Errai UI in your web application.Downloading Polymer ElementsDownload Polymer and the relevant Polymer components, and place them under src/main/webapp. The Polymer elements and code used in our prototype are located in the components/ directory under src/main/webapp/. Detailed instructions on how to download and update Polymer's libraries and components can be found here.Using Polymer Elements in Errai HTML TemplatesIn order to use Polymer elements in your web page with Errai UI, you can create an HTML layout using any combination of Polymer elements and regular HTML elements. For example, this template was created using Polymer's <paper-input> and <paper-button> elements in a <form> element: The above example will also work with Errai Data Binding. You can further create your own custom element and use it in your HTML template. For information on how to create your own Polymer-based element, see Creating elements - Polymer.Note: When importing Polymer elements into your app, the polyfill support script (platform.js) as well as the HTML imports required to use each element must be included in your GWT host page.Integration with GWTTo use Polymer's elements (or your own custom elements) with GWT, we need to create Elements and Widgets, similar to the ones for HTML elements that currently exist in GWT. You can create an Element class for the Polymer element by extending com.google.gwt.dom.client.Element or one of its subclasses. The purpose of this class is to provide Java methods for the Polymer element, by wrapping calls to Polymer's methods and attributes in JSNI code. This Element class represents the Polymer element's DOM implementation.GWT uses Widget classes that wrap Elements, to provide user interaction capabilities. Thus for all UI-based elements, we need to create a Widget class that extends com.google.gwt.user.client.ui.Widget or one of its subclasses. This Widget class should contain methods to handle user interaction with the Polymer element. Refer to the tutorial and to existing GWT Elements and Widgets for examples on how to create your own custom GWT widgets. Here is an example of how to use the Element class and Widget class to interact with the user and with other widgets in your app. The Polymer element used in this example is the <paper-button>. The example shows how to use the PaperButton Element and Widget classes to add an Enter key handler to the ComplaintForm.The PaperButtonElement class provides JSNI methods to access the Polymer element's click() method: The PaperButtonWidget class creates a UI wrapper around the PaperButtonElement: Finally, the ComplaintForm allows the user to submit the form by pressing Enter, which then calls the methods defined in the PaperButton classes above: Using Polymer Elements in your web appAs the example in the previous section illustrates, once you have the requisite Element and Widget classes, you can now use the Polymer element as a regular GWT widget in your web page, using @Inject or manual construction. All of Polymer's functionality should be accessible through the Element class, and you can now use the Widget class to make the element interact with the rest of your web app as needed.Styling Polymer ElementsAn important feature of web components is that they provide style encapsulation from the rest of the document. You can take advantage of this feature to style your web components in Errai web apps as well, by using Polymer's style descriptors such as /deep/ and ::shadow (see this link about Polymer styling for more information).While Polymer's default styling works out of the box, custom styles applied externally to Polymer elements do not. In order to use these styles, you need to add the attribute shim-shadowdom to your style tag. In this tutorial, the shim-shadowdom tag has been added to application.css in the index.html file, to enable external Polymer styling to work.Note: Currently, while Polymer can prevent styles from leaking out of the element's shadow DOM, styles can still leak into the custom elements' shadow trees. Currently only Google Chrome offers complete style encapsulation. For other browsers, you may need to use custom identifiers to style elements outside of Polymer elements.The purpose of this Errai Web Components prototype is to illustrate how to use Polymer elements in your Errai web app. This is an early attempt to investigate how Errai can integrate web components into GWT apps. We welcome community feedback, so please feel free to contact us with questions, comments and suggestions regarding the use of Polymer and web components with Errai.  [Less]
Posted over 10 years ago by [email protected] (Divya Dadlani)
Web Components is an emerging web technology that allows web developers to use custom HTML elements and encapsulation in their applications. Currently, Polymer is the leading web framework that implements this technology. A few members of the Errai ... [More] community have expressed interest in using Polymer elements in their web apps, hence we spent some time creating an early prototype at Errai Tutorial - Web Components. In this blog post, I will outline the steps needed to use Polymer components with Errai UI in your web application.Downloading Polymer ElementsDownload Polymer and the relevant Polymer components, and place them under src/main/webapp. The Polymer elements and code used in our prototype are located in the components/ directory under src/main/webapp/. Detailed instructions on how to download and update Polymer's libraries and components can be found here.Using Polymer Elements in Errai HTML TemplatesIn order to use Polymer elements in your web page with Errai UI, you can create an HTML layout using any combination of Polymer elements and regular HTML elements. For example, this template was created using Polymer's and elements in a element: The above example will also work with Errai Data Binding. You can further create your own custom element and use it in your HTML template. For information on how to create your own Polymer-based element, see Creating elements - Polymer. Note: When importing Polymer elements into your app, the polyfill support script (platform.js) as well as the HTML imports required to use each element must be included in your GWT host page. Integration with GWTTo use Polymer's elements (or your own custom elements) with GWT, we need to create Elements and Widgets, similar to the ones for HTML elements that currently exist in GWT. You can create an Element class for the Polymer element by extending com.google.gwt.dom.client.Element or one of its subclasses. The purpose of this class is to provide Java methods for the Polymer element, by wrapping calls to Polymer's methods and attributes in JSNI code. This Element class represents the Polymer element's DOM implementation.GWT uses Widget classes that wrap Elements, to provide user interaction capabilities. Thus for all UI-based elements, we need to create a Widget class that extends com.google.gwt.user.client.ui.Widget or one of its subclasses. This Widget class should contain methods to handle user interaction with the Polymer element. Refer to the tutorial and to existing GWT Elements and Widgets for examples on how to create your own custom GWT widgets. Here is an example of how to use the Element class and Widget class to interact with the user and with other widgets in your app. The Polymer element used in this example is the . The example shows how to use the PaperButton Element and Widget classes to add an Enter key handler to the ComplaintForm.The PaperButtonElement class provides JSNI methods to access the Polymer element's click() method: The PaperButtonWidget class creates a UI wrapper around the PaperButtonElement: Finally, the ComplaintForm allows the user to submit the form by pressing Enter, which then calls the methods defined in the PaperButton classes above: Using Polymer Elements in your web app As the example in the previous section illustrates, once you have the requisite Element and Widget classes, you can now use the Polymer element as a regular GWT widget in your web page, using @Inject or manual construction. All of Polymer's functionality should be accessible through the Element class, and you can now use the Widget class to make the element interact with the rest of your web app as needed.Styling Polymer Elements An important feature of web components is that they provide style encapsulation from the rest of the document. You can take advantage of this feature to style your web components in Errai web apps as well, by using Polymer's style descriptors such as /deep/ and ::shadow (see this link about Polymer styling for more information).While Polymer's default styling works out of the box, custom styles applied externally to Polymer elements do not. In order to use these styles, you need to add the attribute shim-shadowdom to your style tag. In this tutorial, the shim-shadowdom tag has been added to application.css in the index.html file, to enable external Polymer styling to work. Note: Currently, while Polymer can prevent styles from leaking out of the element's shadow DOM, styles can still leak into the custom elements' shadow trees. Currently only Google Chrome offers complete style encapsulation. For other browsers, you may need to use custom identifiers to style elements outside of Polymer elements. The purpose of this Errai Web Components prototype is to illustrate how to use Polymer elements in your Errai web app. This is an early attempt to investigate how Errai can integrate web components into GWT apps. We welcome community feedback, so please feel free to contact us with questions, comments and suggestions regarding the use of Polymer and web components with Errai.  [Less]
Posted over 10 years ago by [email protected] (Divya Dadlani)
Web Components is an emerging web technology that allows web developers to use custom HTML elements and encapsulation in their applications. Currently, Polymer is the leading web framework that implements this technology. A few members of the Errai ... [More] community have expressed interest in using Polymer elements in their web apps, hence we spent some time creating an early prototype at Errai Tutorial - Web Components. In this blog post, I will outline the steps needed to use Polymer components with Errai UI in your web application.Downloading Polymer ElementsDownload Polymer and the relevant Polymer components, and place them under src/main/webapp. The Polymer elements and code used in our prototype are located in the components/ directory under src/main/webapp/. Detailed instructions on how to download and update Polymer's libraries and components can be found here.Using Polymer Elements in Errai HTML TemplatesIn order to use Polymer elements in your web page with Errai UI, you can create an HTML layout using any combination of Polymer elements and regular HTML elements. For example, this template was created using Polymer's and elements in a element: The above example will also work with Errai Data Binding. You can further create your own custom element and use it in your HTML template. For information on how to create your own Polymer-based element, see Creating elements - Polymer. Note: When importing Polymer elements into your app, the polyfill support script (platform.js) as well as the HTML imports required to use each element must be included in your GWT host page. Integration with GWTTo use Polymer's elements (or your own custom elements) with GWT, we need to create Elements and Widgets, similar to the ones for HTML elements that currently exist in GWT. You can create an Element class for the Polymer element by extending com.google.gwt.dom.client.Element or one of its subclasses. The purpose of this class is to provide Java methods for the Polymer element, by wrapping calls to Polymer's methods and attributes in JSNI code. This Element class represents the Polymer element's DOM implementation.GWT uses Widget classes that wrap Elements, to provide user interaction capabilities. Thus for all UI-based elements, we need to create a Widget class that extends com.google.gwt.user.client.ui.Widget or one of its subclasses. This Widget class should contain methods to handle user interaction with the Polymer element. Refer to the tutorial and to existing GWT Elements and Widgets for examples on how to create your own custom GWT widgets. Here is an example of how to use the Element class and Widget class to interact with the user and with other widgets in your app. The Polymer element used in this example is the . The example shows how to use the PaperButton Element and Widget classes to add an Enter key handler to the ComplaintForm.The PaperButtonElement class provides JSNI methods to access the Polymer element's click() method: The PaperButtonWidget class creates a UI wrapper around the PaperButtonElement: Finally, the ComplaintForm allows the user to submit the form by pressing Enter, which then calls the methods defined in the PaperButton classes above: Using Polymer Elements in your web app As the example in the previous section illustrates, once you have the requisite Element and Widget classes, you can now use the Polymer element as a regular GWT widget in your web page, using @Inject or manual construction. All of Polymer's functionality should be accessible through the Element class, and you can now use the Widget class to make the element interact with the rest of your web app as needed.Styling Polymer Elements An important feature of web components is that they provide style encapsulation from the rest of the document. You can take advantage of this feature to style your web components in Errai web apps as well, by using Polymer's style descriptors such as /deep/ and ::shadow (see this link about Polymer styling for more information).While Polymer's default styling works out of the box, custom styles applied externally to Polymer elements do not. In order to use these styles, you need to add the attribute shim-shadowdom to your style tag. In this tutorial, the shim-shadowdom tag has been added to application.css in the index.html file, to enable external Polymer styling to work. Note: Currently, while Polymer can prevent styles from leaking out of the element's shadow DOM, styles can still leak into the custom elements' shadow trees. Currently only Google Chrome offers complete style encapsulation. For other browsers, you may need to use custom identifiers to style elements outside of Polymer elements. The purpose of this Errai Web Components prototype is to illustrate how to use Polymer elements in your Errai web app. This is an early attempt to investigate how Errai can integrate web components into GWT apps. We welcome community feedback, so please feel free to contact us with questions, comments and suggestions regarding the use of Polymer and web components with Errai.  [Less]
Posted over 10 years ago by [email protected] (Christian Sadilek)
Today we're happy to announce three new Errai releases!Errai 3.0.2.Final and 2.4.5.Final are maintenance releases containing fixes to all reported problems. 3.0.2.Final also contains significant performance improvements for development mode. Browser ... [More] refreshes to load changes should be significantly faster on average due to a newly introduced caching mechanism and several classpath scanning optimizations.Errai 3.1.0.CR1 contains all the same fixes and improvements as well as number of new features requested in our forums. Support for JSR-356 WebSockets: ErraiBus can now leverage JSR-356 WebSocket support when available (i.e. in WildFly 8.0 or higher). Check out our reference guide for details. Thanks to Michel Werren for the pull requests! Built-in offline manifest linker: Errai now provides an offline linker to generate HTML5 cache manifest files at compile time. PushState support in Errai Navigation: Errai Navigation can now optionally leverage HTML5 pushState (using Johannes Barop's great GWT library). This allows for more flexibility when designing your page URLs (i.e. you can now make use of path parameters). Errai Security Enhancements: Errai Security now has a Keycloak integration module for SSO support and allows for fine-grained authorization rules. The last item deserves more details. So, here they are, provided by Max Barkley who also did most of the implementation work: Errai Security provides a uniform, declarative syntax for securing RPC Services, Messaging Services, Navigation Pages, and UI elements (you can read more here). We've listened to your feedback and have some new features in Errai Security.Fine-Grained Authorization with Custom RolesIn Errai 3.0, roles must be specified as String constants. In Errai 3.1, it is now possible to define a RequiredRolesProvider that can return your custom implementation of the Role interface. By overriding the equals and hashcode methods with your own role matching logic, it is now possible to create more fine-grained authorization rules.Here is an example two RPC Services that both require the same roles, but one uses the String role syntax while the other uses a RequiredRolesProvider: Note that implementations RequiredRolesProvider will be looked up through the bean manager, so they can inject dependencies and use other IOC features.Keycloak SSO Integration JBoss Keycloak is a framework that makes Single Sign On (SSO) and Social Media logins a walk in the park. In Errai 3.1, Errai Security has a keycloak module that provides an implementation of the AuthenticationService that can accept logins from Keycloak.The best part is that you can still use this feature with the PicketLinkAuthenticationService (or your own custom implementation) if you want to also allow logins from your own database. When added to the classpath, the KeycloakAuthenticationService will wrap any other AuthenticationService it finds. This way, you can either direct your users to a Keycloak server for SSO, or call the AuthenticationService.login method to log in through an alternate service.You can read about configuring Keycloak with your app here, or follow this README to see it in action with the Errai Security demo.Happy coding and please keep the feedback and feature requests coming! [Less]
Posted over 10 years ago by [email protected] (Christian Sadilek)
Today we're happy to announce three new Errai releases!Errai 3.0.2.Final and 2.4.5.Final are maintenance releases containing fixes to all reported problems. 3.0.2.Final also contains significant performance improvements for development mode. Browser ... [More] refreshes to load changes should be significantly faster on average due to a newly introduced caching mechanism and several classpath scanning optimizations.Errai 3.1.0.CR1 contains all the same fixes and improvements as well as number of new features requested in our forums.Support for JSR-356 WebSockets: ErraiBus can now leverage JSR-356 WebSocket support when available (i.e. in WildFly 8.0 or higher). Check out our reference guide for details. Thanks to Michel Werren for the pull requests!Built-in offline manifest linker: Errai now provides an offline linker to generate HTML5 cache manifest files at compile time.PushState support in Errai Navigation: Errai Navigation can now optionally leverage HTML5 pushState (using Johannes Barop's great GWT library). This allows for more flexibility when designing your page URLs (i.e. you can now make use of path parameters).Errai Security Enhancements: Errai Security now has a Keycloak integration module for SSO support and allows for fine-grained authorization rules.The last item deserves more details. So, here they are, provided by Max Barkley who also did most of the implementation work:Errai Security provides a uniform, declarative syntax for securing RPC Services, Messaging Services, Navigation Pages, and UI elements (you can read more here). We've listened to your feedback and have some new features in Errai Security.Fine-Grained Authorization with Custom RolesIn Errai 3.0, roles must be specified as String constants. In Errai 3.1, it is now possible to define a RequiredRolesProvider that can return your custom implementation of the Role interface. By overriding the equals and hashcode methods with your own role matching logic, it is now possible to create more fine-grained authorization rules.Here is an example two RPC Services that both require the same roles, but one uses the String role syntax while the other uses a RequiredRolesProvider: Note that implementations RequiredRolesProvider will be looked up through the bean manager, so they can inject dependencies and use other IOC features.Keycloak SSO IntegrationJBoss Keycloak is a framework that makes Single Sign On (SSO) and Social Media logins a walk in the park. In Errai 3.1, Errai Security has a keycloak module that provides an implementation of the AuthenticationService that can accept logins from Keycloak.The best part is that you can still use this feature with the PicketLinkAuthenticationService (or your own custom implementation) if you want to also allow logins from your own database. When added to the classpath, the KeycloakAuthenticationService will wrap any other AuthenticationService it finds. This way, you can either direct your users to a Keycloak server for SSO, or call the AuthenticationService.login method to log in through an alternate service.You can read about configuring Keycloak with your app here, or follow this README to see it in action with the Errai Security demo.Happy coding and please keep the feedback and feature requests coming! [Less]
Posted over 10 years ago by [email protected] (Christian Sadilek)
Today we're excited to announce the Errai 3.0.0.Final release! Don't worry if a feature you wanted didn't make it in yet. We'll switch our master branch to 3.1.0-SNAPSHOT where we'll be working on new features and merging your pull requests ;). Fixes ... [More] will also be released as 3.0.x, if required.Check out the release notes for details on all fixes and improvements of this release. Also make sure to read our recent blog posts introducing all new features of Errai 3.0 (Part 1 on RPC enhancements, Part 2 on Errai Security, Part 3 as a summary of smaller features, and a description of our Forge Addon).A big thank you to everyone who contributed features and patches as well as everyone who provided feedback and shared their experiences with us. We love working on open source.Please join us on Freenode #errai, the errai-dev mailing list, or on our community forums.Happy Coding! [Less]
Posted over 10 years ago by [email protected] (Christian Sadilek)
Today we're excited to announce the Errai 3.0.0.Final release! Don't worry if a feature you wanted didn't make it in yet. We'll switch our master branch to 3.1.0-SNAPSHOT where we'll be working on new features and merging your pull requests ;). Fixes ... [More] will also be released as 3.0.x, if required.Check out the release notes for details on all fixes and improvements of this release. Also make sure to read our recent blog posts introducing all new features of Errai 3.0 (Part 1 on RPC enhancements, Part 2 on Errai Security, Part 3 as a summary of smaller features, and a description of our Forge Addon).A big thank you to everyone who contributed features and patches as well as everyone who provided feedback and shared their experiences with us. We love working on open source.Please join us on Freenode #errai, the errai-dev mailing list, or on our community forums.Happy Coding! [Less]
Posted over 10 years ago by [email protected] (Christian Sadilek)
Today we're excited to announce the Errai 3.0.0.Final release! Don't worry if a feature you wanted didn't make it in yet. We'll switch our master branch to 3.1.0-SNAPSHOT where we'll be working on new features and merging your pull requests ;). Fixes ... [More] will also be released as 3.0.x, if required.Check out the release notes for details on all fixes and improvements of this release. Also make sure to read our recent blog posts introducing all new features of Errai 3.0 (Part 1 on RPC enhancements, Part 2 on Errai Security, Part 3 as a summary of smaller features, and a description of our Forge Addon).A big thank you to everyone who contributed features and patches as well as everyone who provided feedback and shared their experiences with us. We love working on open source.Please join us on Freenode #errai, the errai-dev mailing list, or on our community forums.Happy Coding! [Less]
Posted almost 11 years ago by [email protected] (Christian Sadilek)
This is the third post in a series describing new features in Errai 3.0. This post is a summary of some of the smaller features and enhancements coming in 3.0.0.Final.Improved HTML Form SupportAsynchronous form submission can make it difficult to ... [More] trigger useful events in the web browser (such as prompting to remember a user's password). To help you overcome this issue, Errai UI now contains a base class for @Templated Widgets that provides better HTML form support.By extending the AbstractForm class and invoking its submit method, Errai simulates native HTML form submission. Below is an example login form that causes modern browsers to prompt the user to remember a password when the "Login" button is clicked.Test Generation with the Errai Forge AddonIf you haven't heard, there is an Errai Addon for JBoss Forge 2. This addon can set up Errai in an existing Java project for running in Dev Mode or compiling to production mode. But in the 3.0.0.Final release, you will be able to use the addon to generate unit and integration tests.Unit tests are generated with GWT Mockito. Mockito is a test framework that allows you to inject mocks into classes and assert conditions on how these mocks are used. GWT Mockito adds extra GWT compatibility, allowing you to test classes with GWT.create calls or JSNI methods.Integration tests extend the AbstractErraiCDITest (which in turn extends the GWTTestCase). In addition to the normal GWTTestCase functionality, the AbstractErraiCDITest initializes the Errai framework, including the Message Bus and IoC/CDI container.WildFly 8.0 Support for Dev ModePreviously we announced an improved Dev Mode setup using the JBossLauncher. This setup allowed the GWT Dev Mode to control a full JBoss 7 instance, making it easier to develop a GWT app using Java EE on the server.It is now possible to use the this launcher with WildFly 8.0. If you haven't yet, give it a try since there have been many performance improvements to WildFly 8.0 that make a noticeable difference in startup time.Asynchronous IOC with Fragment ControlErrai's @LoadAsync annotation allows for managed beans to be loaded asynchronously. That means the code for these beans will reside in a separate JavaScript file that will be downloaded the first time it is needed. In Errai 3.0.0.Final you have more control over these split points. A code fragment name can optionally be specified using a Java class literal (i.e. @LoadAsync(Admin.class) to group all beans related to admin functionality). GWT's code splitter will then put the code of all managed bean types with the same fragment name into the same code fragment (JavaScript file).Error Detection for Common Pitfalls in Your IDEBy adding the following dependency to your project you will get automatic error detection for common Errai pitfalls directly in your IDE. While this covers an increasing amount of pitfalls, we are happy to accept your contributions. If you can think of more checks we should include please let us know or send us a pull request! Note that in Eclipse you will have to manually enable annotation processing: Go to Eclipse Workspace Preferences->Maven->Annotation Processing and select the "Automatically Configure JDT APT" radio button. In Eclipse you will also need to install the m2e-apt plugin. That is all for today. Happy Coding! [Less]
Posted almost 11 years ago by [email protected] (Christian Sadilek)
This is the third post in a series describing new features in Errai 3.0. This post is a summary of some of the smaller features and enhancements coming in 3.0.0.Final.Improved HTML Form SupportAsynchronous form submission can make it difficult to ... [More] trigger useful events in the web browser (such as prompting to remember a user's password). To help you overcome this issue, Errai UI now contains a base class for @Templated Widgets that provides better HTML form support.By extending the AbstractForm class and invoking its submit method, Errai simulates native HTML form submission. Below is an example login form that causes modern browsers to prompt the user to remember a password when the "Login" button is clicked.Test Generation with the Errai Forge AddonIf you haven't heard, there is an Errai Addon for JBoss Forge 2. This addon can set up Errai in an existing Java project for running in Dev Mode or compiling to production mode. But in the 3.0.0.Final release, you will be able to use the addon to generate unit and integration tests.Unit tests are generated with GWT Mockito. Mockito is a test framework that allows you to inject mocks into classes and assert conditions on how these mocks are used. GWT Mockito adds extra GWT compatibility, allowing you to test classes with GWT.create calls or JSNI methods.Integration tests extend the AbstractErraiCDITest (which in turn extends the GWTTestCase). In addition to the normal GWTTestCase functionality, the AbstractErraiCDITest initializes the Errai framework, including the Message Bus and IoC/CDI container.WildFly 8.0 Support for Dev ModePreviously we announced an improved Dev Mode setup using the JBossLauncher. This setup allowed the GWT Dev Mode to control a full JBoss 7 instance, making it easier to develop a GWT app using Java EE on the server.It is now possible to use the this launcher with WildFly 8.0. If you haven't yet, give it a try since there have been many performance improvements to WildFly 8.0 that make a noticeable difference in startup time.Asynchronous IOC with Fragment Control Errai's @LoadAsync annotation allows for managed beans to be loaded asynchronously. That means the code for these beans will reside in a separate JavaScript file that will be downloaded the first time it is needed. In Errai 3.0.0.Final you have more control over these split points. A code fragment name can optionally be specified using a Java class literal (i.e. @LoadAsync(Admin.class) to group all beans related to admin functionality). GWT's code splitter will then put the code of all managed bean types with the same fragment name into the same code fragment (JavaScript file).Error Detection for Common Pitfalls in Your IDEBy adding the following dependency to your project you will get automatic error detection for common Errai pitfalls directly in your IDE. While this covers an increasing amount of pitfalls, we are happy to accept your contributions. If you can think of more checks we should include please let us know or send us a pull request! Note that in Eclipse you will have to manually enable annotation processing: Go to Eclipse Workspace Preferences->Maven->Annotation Processing and select the "Automatically Configure JDT APT" radio button. In Eclipse you will also need to install the m2e-apt plugin. That is all for today. Happy Coding! [Less]