As far as I can tell, there are two ways to set the IDs for web elements from within GWT. I need to perform Selenium automated testing, and would appreciate insight into the relative advantages of each technique.
Option 1: the generally accepted method
uiObject.ensureDebugId("idForMyElement");
This solution is well documented, and officially supported by google. However it comes with some disadvantages:
My team will have to add lines to every package's gwt.xml file like so:
<inherits name='com.google.gwt.user.Debug' />
Furthermore, the Debug class prepends "gwt-debug" to IDs by default. I realize I can change this behavior, but I don't like adding complexity where I can help it.
Option 2: use a generic setAttribute call
uiObject.getElement().setAttribute("id", "idForMyElement);
This seems cleaner to me- are there any downsides I might be overlooking?
Relevant resources:
How can I set id for GWT widgets in UiBinder?
https://code.google.com/p/google-web-toolkit/issues/detail?id=4176
The first option is better because you can compile out debug ids from your production code, making it smaller.
With the second option ids will be there even when you don't need them anymore.
Related
We have a rather large application, with a great deal of dynamic content. Is there anyway to force struts to use a database for the i18n lookups, instead of properties files?
I'd be open for other ways to solve this as well, if anyone has ever done i18n with dynamic content.
I don't know of an easy plug-and-play solution for this, so you will probably have to implement it yourself -- plan on spending quite a bit of time just coming to grips with how the localization features of struts 2 (and XWork) are implemented. The key will probably be to provide your own implementation of com.opensymphony.xwork2.TextProvider (and tell struts to use it by providing a <bean> tag in struts.xml). I can think of at least two ways of fitting this into the overall architecture:
Have your TextProvider implementation access the database directly. In the spirit of YAGNI, this is probably the best way to start (you can always refactor later, if necessary).
Alternatively, you could place the database code into an implementation of Java's ResourceBundle interface, which is what XWork uses internally. To me this sounds like an even more design-heavy approach, but on the plus side there are some articles around describing how to do this.
No, there is no built-in way to have Struts2 load localized content from a database. You would need to write that yourself.
What are your requirements? Do you need for users to be able to dynamically change field prompts, error messages, etc.?
You may be able to do something like that by building a custom interceptor. You could have the interceptor read all the key value pairs from your database and inject them into the value stack. The only thing I am not sure about, not really having messed with i18n with struts before, is if the i18n stuff pulls that information from the value stack. If not, I am not sure if maybe you could do something else in the interceptor to load up the information.
Building a custom interceptor is not too terribly complicated. There are plenty of tutorial sites out there, including (brace for self promotion here) my blog: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html.
Use properties files just for static content, like labels, messages etc.
For dynamic content start with a database table that includes a language-code-id for every language you want to use. All the dynamic content entries that are already translated go with their respective language-code-id added to their primary key. If a translation is missing, you can program your application to fall back to your default language in order to make things easier until the right translation is present.
Let your users provide their contributions in the language they like and store it with the appropriate language-id. Someone should provide the translation to the other languages in order to make the contribution complete.
...
PRIMARY KEY (`subject_id`,`language_id`),
...
I'm rather unexperienced in GWT, and I have large codebase with working project in this technology. My task refers to assigning id's to html elements witch will be used in automatic testing. We can't use some dynamically assigned id's because in automatic test we have to specify exact values of id's. My way for now was to use method ensureDebug(id), written by hand in code for specific elements.
I think that doing it this way mean that code will be more spaghetti-like, with mixed ensureDebug(id) methods usages there and here. I was thinking if there is any way of doing it that will be more manageable and cleaner than current. Is is maybe possible to use AOP? (I have never used AOP, so I don't know if it is any good idea, or possible in GWT) Or maybe other way than using ensureDebug?
You also can set the IDs for HTML elements like
element.setId("myId");
But this is as much spaghetti like as your approach adding the IDs in the code.
Another possibility would be to use an UiBinder and set the id there. With this approach you have all your ui elements of one view, which should have an id, at one place. With bootstrap for example it would look like this:
<b:TextBox ui:field="searchTextBox" b:id="search-text-box"/>
Like this you can access the field in your view-class via searchTextBox and the id search-text-boxis added to the HTML element (which you could also use for styling etc.)
We have faced same issue for our project while adding test automation. As per my knowledge unfortunately GWT doesn't support anything like AOP yet. So we have to follow any of the spaghetti-like approach only from one mentioned above by #mxlse or the one you are already following.
Based on my experience I can recommend you to create separate constant/property at client or server end. Use this file to save all your id's which you can share latter on with test team as well.
I am tired of manually finding locators (id,xpath,css,linkText etc..) for web elements from my web page source. It also consumes more efforts. So, to avoid that I want to write a code that interacts with page source directly and generates locators details (e.g. id="xyz" , xpath ="html/body/table/tr/td/a" etc.)
To achieve this ,I think I can generate ID locator by using split() function of String object. But, what I don't know is how to generate xpaths, css and linkText locators for all page components?
Although I'd generally recommend to construct XPath expressions on your own (as you can better exploit things to mach against like class attributes), probably the most reasonable and convenient automatic way to determine XPath expressions for selenium is to use either Firebug's or Chrome Developer Tool's "Find XPath" feature. They both at least use #id attributes to shorten XPath expressions.
If you want to write some code yourself, eg. for embedding in other tools you use, you might want to have a look at the answers of "PHP XML - Find out the path to a known value" which solves the problem in PHP, or another one with answers for Javascript: "Javascript get XPath of a node".
If you're using any tools not working on the DOM (Selenium/Firebug/Chrome Dev' Tools/JavaScript will do), watch out for the problems I described in "Why does my XPath query (scraping HTML tables) only work in Firebug, but not the application I'm developing?".
There are (at present) no "tools" that do even a marginally decent job of synthesizing reliable and concise xpath or css based locators. I've been writing selenium and HTML/CSS code for nearly the duration of the industry, and the so-called CASE-methods that purport to do this job better than humans produces laughably flawed output more often that it generates useful material. However, I would add a codicil: there is hope.
By taking careful stock of the various XPath and CSS methods (see http://www.w3schools.com/xpath/xpath_axes.asp for some general guidelines) and using only the most minimal locator strings that will pass muster in Firebug, Selenium IDE and other similar plug-ins, one can progress gradually towards a better approach. In general one should (where possible) use only one component from an object's attribute list and avoid using dynamically defined quantities. Best practices would encourage picking class, name or id only if they are "immutable".
Mutability is a tricky issue: simply dragging a cursor over an object or clicking on it may change the class or css characteristics. Sometimes this can be surmounted by using only the "fixed" portion of the offending attribute. For example, a class might initially be 'tabContent', but when the cursor is placed over the corresponding object it might change to 'tabContentMouseOver'. You get the idea. By using an xpath locator string //*[contains(#class,'tabContent')] you stand a better than even chance of hitting the desired object, irrespective of whether it is clicked, highlighted, or even disabled.
The next "trick" I'd encourage you to consider is using the "buddy" principle; many objects (button-like ones in particular) nowadays consist of an image with no dynamic properties wrapped by a div that manages its event-driven behavior. For such situations you might find that //div[#eventproxy='tabObject']/following::img[contains(#src,'tabImage') and text()='Contents'] or something similar will cover all the bases. Contents will vary with your situation of course.
Make vigorous use of the hierarchical axes methods ('following' is one I use quite often), but only where necessary; sometimes '//' will suffice instead.
Penalize yourself for every unnecessary character, and reward yourself for methods which are concise and can weather frequent and severe code changes. Above all, persevere.
In general I avoid using "pure" CSS locators for the following reason -- they were never intended as locators. "Cascading Style Sheets" by their very nature are designed to impact the maximum number of web objects possible, and are very rarely unique to any one piece of content. Web-coders are notorious for changing these on the fly to produce spiffy new effects or restructure content to suit customer demands; why hitch your tests to content that is known to fluctuate? Besides, everything CSS can do (and I do mean EVERYTHING) can also be done inside XPaths if you so choose.
The canard about XPaths being "slower" than CSS methods I believe has been disproved often enough that it should be taken with several tablespoons of salt. Still, if you really feel more comfortable with CSS techniques, go for it! Experience will educate you better than any blurb you find in stackoverflow ever will.
I want to create a web site which can be viewed with two languages, one LTR and one RTL. This means that all content should be shown in either of the two languages.
My framework is Spring, and I'm using Tiles2, but I think this question is not framework specific.
The obvious solution to supporting two languages is having everything doubled (all JSP's, fragments, etc.), and you get the part of the tree which fits the language you chose. But this causes problems when changing the web site (you might forget to update the other JSP's), and is not scalable (try doing this for 5 or 10 languages).
I know I can use properties files to host strings for the different languages, but then my web site would be a huge collection of spring:message tags and will be a lot harder to maintain (what happens if I have a paragraph of 100 lines, does this all go into a single properties line?)
Is there any kind of framework, plugin, other, which solves this problem? Has anyone come across a clever solution to this problem?
I've never realized a complete project, just some tests. I think this problem is not so big as it seems if you follow some simple rules. Here is what I would try to do:
Specify direction with <body dir='ltr/rtl'>. This is preferred versus CSS direction attribute.
Avoid different left/right margins or paddings in all CSS. If you must break this rule, probably you'll need to use two different files (ltr.css and rtl.css) containing all these different elements.
Sometimes you'll need to move some elements from left to right or vice versa. For example, in LTR you want a menu on the left, but in RTL you want it on the right. You can achieve this using CSS, but this sometimes is complicated if you are not an expert and you must test it in all browsers. Another option is to use some IF depending on the case. This last option will fit very well if you use a grid based CSS library, like Bootstrap.
Choose carefully which CSS and JS libraries you'll use. Obviously, pick the ones which offer RTL/LTR support.
Don't worry too much about the images. If you must change one image depending on the language is probably because it has some text in it. So, you must use different images anyway. This is a problem related to i18n, not a text direction issue.
Don't let your customer to be too much fussy about it. I think that with these rules (and maybe some more) you can get a good result. But if your customer starts complaining about one pixel here and another one there, you'll need to complicate all this and probably is not necessary.
About your language properties file. Yes, use them. Always. This is a good practice even when you are only using one language: HTML structure is separated from content, is very easy to correct or translate, some words or sentences are in only one file...
Usually, web frameworks are used to build web applications rather than web sites, and there are quite few long static paragraphs. Most of the content is dynamic and comes from a database. But yes, the usual way of doing is to externalize everything to resource bundles, usually in the form of properties files.
Putting a long paragraph in a properties file doesn't cause much problem, because you can break long paragraphs into multiple lines by ending each line by a backslash:
home.welcomeParagraph=This is a long \
paragraph splitted into several lines \
thanks to backslashes.
RTL and LTR is one of the upper and more difficult i18n problems.
Basically its a Problem of the view-scope of the MVC-Model. This may also includes pictures and emotional differences like the color of the skin of people. In this case you better abadon to the solution HTML+CSS gives you.
In example:
<style type="text/css">
*:lang(ar) { direction:rtl }
*:lang(de) { direction:ltr }
</style>
The best practice is to ask members of the audience-group about what effect the webpages have to them.
I agree to most of solutions provided here. Your problem is more design (architecturally) oriented rather than technical. You need to choose path whether you need to keep this logic of internationalization on server (java) side or in static files.
In case you want to go for java side (preferable solution), you need to keep two properties file and use jstl tags. This minimizes your work in case you want to add another language in future. This is maintainable solution. I have seen applications supporting more than 15 languages and time zones. In fact release process gets pretty easy.
In case you want to go for keeping multiple css and other static files, you will soon find things running out of your hands pretty soon. I dont think this is a maintainable solution.
Said all this, I will leave this choice to the architect of application. He will be able to judge which way to go based upon the nature of application and constraints given to him.
You don't want to use everywhere. That's a pity because it is just the way you should do it. It is a bad practice to keep hard-coded texts in a jsp if you need internationalization.
Furthermore, Most of the modern IDE allows you to go to the variable declaration by doing ctrl+left click (or hovering the key) so that having a lot of variables in your code should not be a problem for maintenance.
First, you must distinguish, for each text element, whether it is a user interface element (e.g. button label) or redactionnal content.
user interface element labels will be stored in properties file that will have to be translated for each supported language (and provide a default value as a fall back)
redactionnal content will be stored in a content management system that you will organize in order to find easily a localized version of your content
I recently read this article on ClientBundle and under the Levers and knobs section, see these two entries:
ClientBundle.enableInlining is a deferred-binding property that can be used to disable the use of data: URLs in browsers that would otherwise support inlining resource data into the compiled JS.
ClientBundle.enableRenaming is a configuration property that will disable the use of strongly-named cache files.
I'm having a tough time visualizing these in action and understanding what they do. Where do you set these properties? Why would you set them (i.e., when would I want to "disable the use of data", or "disable the use of strongly-named cache files")? Can someone provide a real-world use case and perhaps some code snippets for me? Thanks in advance!
Where do you set these properties?
Deferred-binding properties are set in your gwt.xml with <set-property>.
See https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsDeferred
Why would you set them (i.e., when would I want to "disable the use of data", or "disable the use of strongly-named cache files")?
For debugging, or if the performance boost they're supposed to bring to your app actually does more harm than good (enableInlining'), or if you need/want to share the resources with other scripts/apps (enableRenaming`).
Can someone provide a real-world use case and perhaps some code snippets for me?
You'll know it when you need them. Until then, ignore them.
In case this is still useful, I have a real-world example of needing to disable inlineing.
But first, just to clarify the code needed its simply;
<set-property name="ClientBundle.enableInlining" value="false" />
In your XML to disable the use of DataURLs and use image strips instead
I had to do this in my code, because my project requires animated images. Even a basic sprite with just a few frames has very bad performance when using DataURLs. The browsers just struggle to update and display the images at anywhere near a reasonable framerate.
By comparison, the use of image strips, vastly speeds up performance. The browser merely has to change the cropping.
In fact, given the lack-luster browser support for animated PNG's, if you need animated images, this is probably the current best way to do it.