Wicket: override browserinfopage - wicket

I'm enabling Wicket to gather the browser information:
getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
Therefore I'm seeing a BrowserInfoPage with some standard message. I want to prevent users from seeing this message.
I'm trying to override BrowserInfoPage and want to leave it blank, as it shown here: http://markmail.org/message/fqbunzoddmh3dplx
I'm getting the following error.
Unexpected RuntimeException Last cause: The component(s) below failed to render.
A common problem is that you have added a component in code but forgot to reference
it in the markup (thus the component will never be rendered).
And a list of components from original BrowserInfoPage. I understand that it grabs those components from a super class. But how can I get rid of all that?

Create your own custom browser info page:
import org.apache.wicket.markup.html.pages.BrowserInfoPage;
public class CustomBrowserInfoPage extends BrowserInfoPage {
private static final long serialVersionUID = 1L;
}
Override newBrowserInfoPage in your Session class:
protected WebPage newBrowserInfoPage()
{
return new CustomBrowserInfoPage();
}
Then copy the BrowserInfoPage.html file from org.apache.wicket.markup.html.pages in the wicket-core.jar and customize it... It should be in the same folder as your CustomBrowserInfoPage.java file.

I would guess that you have to create an empty HTML file called "CustomBrowserInfoPage.html" next to your CustomBrowserInfoPage.java so Wicket takes your HTML file and not the one from the parent class.

Most likely you are seeing something like:
Last cause: The component(s) below failed to render. Possible reasons could be that: 1) you have added a component in code but forgot to reference it in the markup (thus the component will never be rendered), 2) if your components were added in a parent container then make sure the markup for the child container includes them in <wicket:extend>.
1. [WebMarkupContainer [Component id = link]]
2. [BrowserInfoForm [Component id = postback]]
3. [Form [Component id = postback]]
4. [TextField [Component id = navigatorAppName]]
5. [TextField [Component id = navigatorAppVersion]]
6. [TextField [Component id = navigatorAppCodeName]]
7. [TextField [Component id = navigatorCookieEnabled]]
8. [TextField [Component id = navigatorJavaEnabled]]
9. [TextField [Component id = navigatorLanguage]]
10. [TextField [Component id = navigatorPlatform]]
11. [TextField [Component id = navigatorUserAgent]]
12. [TextField [Component id = screenWidth]]
13. [TextField [Component id = screenHeight]]
14. [TextField [Component id = screenColorDepth]]
15. [TextField [Component id = utcOffset]]
16. [TextField [Component id = utcDSTOffset]]
17. [TextField [Component id = browserWidth]]
18. [TextField [Component id = browserHeight]]
19. [TextField [Component id = hostname]]
Most of these components are in BrowserInfoForm and are in fact needed in order for the form to collect the info.
The "link" and "postback" components are in BrowserInfoPage, and thus must be in your html markup if you subclass this.
The BrowserInfoPage markup might vary slightly by wicket version (but likely not much). Mine is:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta wicket:id="meta" http-equiv="refresh" />
</head>
<body onload="javascript:submitform();">
If you see this, it means that both javascript and meta-refresh are not support by
your browser configuration. Please click <a wicket:id="link" href="#">this link</a> to
continue to the original destination.
<div wicket:id="postback"></div>
</body>
</html>
In order to do the work of collecting the client info, your markup needs to include the <body onload="javascript:submitform();"> and the form itself which is in the "postback" section.
What you're seeing is probably the message starting "If you see this ...". In my attempts to reproduce your issue, I've never seen this, but I suspect it may show for a moment before a refresh/redirect to the original destination. You can likely eliminate it by using something like this for your "CustomBrowserInfoPage.html":
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta wicket:id="meta" http-equiv="refresh" />
</head>
<body onload="javascript:submitform();">
<a wicket:id="link" href="#"></a>
<div wicket:id="postback"></div>
</body>
</html>
If any of the fields from the BrowserInfoForm are visible it will be messier to hide them. But I don't think they show anyway.
Be aware however, that if you do this, people who disable JavaScript will see a blank page and have no way to get to your real page. That's the reason for the message and the "link".

Related

Wicket: automatic field validation does not work

I have an integer field and when i enter a non integer value (let's say a symbolic one) the Feedback panel should be triggered automatically with default message, but it does not work, I have to call it in onError method of the form by method error().
This is the textField, that i use:
RequiredTextField<Integer> intField =
new RequiredTextField<>("intValue", integerValue,Integer.class);
this is my simple FeedBackPanel:
fragment.add(new FeedbackPanel("feedback"));
it works only when i call method error() in method onError() of the form.
Could you show us how you create your Form and the Model you use? As far as I understand it you will want to bind a Model to your Fields. My best guess is that your Model does not have a property "intValue".
You might want to (re)visit the Wicket Wiki "More on Models".
I'm not sure how you are setting your model. And once you add RequiredTextField it will not allow you empty and since you set the Integer type it will not allow characters to be entered.
I have tried some code snippet which is working perfectly and validating.
HomePage.html
<html xmlns:wicket="http://wicket.apache.org">
<body>
<form wicket:id="someForm">
<div wicket:id="feedback"></div>
<input type="text" wicket:id="requiredText">
<input type="submit" value="submit">
</form>
</body>
</html>
HomePage.Java
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;
public HomePage(final PageParameters parameters) {
super(parameters);
Form form = new Form("someForm");
form.add(new FeedbackPanel("feedback"));
IModel integerValue= Model.of("");
form.add(new RequiredTextField("requiredText",integerValue,Integer.class));
add(form);
}
}
Please let me get back to me on this incase if you need anything .

How can I set a meta description tag in Sailsjs using ejs templates?

I would like to be able to set the description meta tag from the sails controller action. I have searched all over, but the only example involves the page title. This is my first node.js and sailsjs site, am I going about this the wrong way?
Something like this:
module.exports = {
index: function (){
res.view(
{
title: 'The Title Text',
metaDescription: "The Description Text"
});
}
};
Yes, this is correct. You can insert in your template with
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<meta name="description" content="<%= metaDescription %>">
Docs and examples can be found here:
http://sailsjs.org/#!/documentation/concepts/Views/Locals.html
http://sailsjs.org/#!/documentation/reference/res/res.view.html
Thank you #Bulkin for pointing me in the right direction. Here is the solution that worked for me. I put the local variable in the layout template and it worked by passing the meta tag text from the controller for all pages, but the home page. The home page kept throwing an error as seeing "metaDescription", as undefined. The fix was to set the local variable in the home page route of config/routes.
module.exports.routes = {
'/': {
view: 'home/index',
locals: {
metaDescription: "Description Text"
}
}
};

How to calculate the time taken to load module in gwt?

I am using a custom gridview widget and large amount of data(say 1000 rows) assigned to it.I know that it will take more time.And I want to know how much time it exactly taking to load the grid.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="Custom.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>CustomWidget</title>
<script type="text/javascript" language="javascript" src="mywidget/mywidget.nocache.js">
function startTime()
{
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
// add a zero in front of numbers<10
m=checkTime(m);
s=checkTime(s);
document.getElementById('txt').innerHTML=h+":"+m+":"+s;
t=setTimeout(function(){startTime()},500);
}
function checkTime(i)
{
if (i<10)
{
i="0" + i;
}
return i;
}
</script>
</head>
<body onload="startTime()">
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<div id="txt"></div>
</body>
</html>
But not able display time..and its working when executing as single html page.
Another two ways along with #Braj answer
1.Using Speed Tracer you are able to get a better picture of where time is being spent in your application. This includes problems caused by:
Javascript parsing and execution
Layout
CSS style recalculation and selector matching
DOM Event handling
Network resource loading
Timer fires
XMLHttpRequest callbacks
Painting
Fallow this link Speed Tracer and to Crome(click on free) ,works with Crome only
2.You can edit, debug, and monitor CSS, HTML, and JavaScript live in any web page
With this we can get how much time each function taken , how many times is called and % of total time
but its works with fire fox only.
Fallow this link FireBug.Click on Console and enable Profile to see the performance of each function.
Sometimes you may get obfuscated function names.To avoid this project>Google>GWT Compile>Select output style as Pretty
Try this one
Steps to follow:
create a hidden div that have a information about current time before downloading nocache.js
Once nocache.js is loaded it will call EntryPoint#onModuleLoad() method of your entry point class.
Compare the time to get the time taken
HTML/JSP:
<body>
<div id="timeinfo" style="visibility: hidden;"></div>
<script type="text/javascript">
var today = new Date();
document.getElementById("timeinfo").innerHTML = today.getTime();
</script>
<script type="text/javascript" src="mywidget/mywidget.nocache.js"></script>
</body>
Entry point class:
public class MyWidget implements EntryPoint {
public void onModuleLoad() {
RootPanel timeinfo = RootPanel.get("timeinfo");
long startTime = Long.valueOf(timeinfo.getElement().getInnerHTML());
long endTime = System.currentTimeMillis();
System.out.println(new Date(startTime));
System.out.println(new Date(endTime));
System.out.println("Total time taken=" + (endTime - startTime) + " ms.");
RootPanel.getBodyElement().removeChild(timeinfo.getElement());
...
}
}
output:
Tue Apr 22 16:55:49 IST 2014
Tue Apr 22 16:56:03 IST 2014
Total time taken=14479 ms.
Open console in your browser. Click on the Network tab. Reload the page. See how long it takes to load each resource.

Embed google-plus in GWT

I am trying to embed Google-Plus into my GWT Application. I would like it to be embedded into a HorizontalPanel. I did read +1button developers google. I didn't find any post about this particular problem in stackoverflow. My problem might be that I don't understand how to include the js into a GUI component. I would appreciate an Example of how to add the Google+ code into a Panel.
Here is how to do it:
Documentation:
<!-- Place this tag in your head or just before your close body tag -->
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<!-- Place this tag where you want the +1 button to render -->
<g:plusone></g:plusone>
in GWT:
private void drawPlusOne() {
String s = "<g:plusone href=\"http://urltoplusone.com\"></g:plusone>";
HTML h = new HTML(s);
somePanel.add(h);
// You can insert a script tag this way or via your .gwt.xml
Document doc = Document.get();
ScriptElement script = doc.createScriptElement();
script.setSrc("https://apis.google.com/js/plusone.js");
script.setType("text/javascript");
script.setLang("javascript");
doc.getBody().appendChild(script);
}
I've personally never embedded the +1 button in GWT, but the linked article seems pretty self explanatory.
In the section "A Simple Button", it indicates that the simplest way of implementing GooglePlus integration is to add this:
<script src="https://apis.google.com/js/plusone.js" />
<g:plusone></g:plusone>
First, the <script> tag should be included in your .gwt.xml file.
Then I'd implement the <g:plusone></g:plusone> like this:
public class GPlusOne extends SimplePanel {
public GPlusOne () {
super((Element)Document.get().createElement("g:plusone").cast());
}
}
(Note that this code is untested, but it's based on the simple concept that a SimplePanel can be extended to compile as any HTML element.)
Then you'd use the new GPlusOne element wherever you'd want the button to show.
I found a better way to do it:
Follow this example to have the button work on invocation on a normal html page (you can try one here http://jsfiddle.net/JQAdc/)
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="https://apis.google.com/js/plusone.js">
{"parsetags": "explicit"}
</script>
<script type="text/javascript">
function gPlusBtn(id, params) {
/* window.alert("searching for "+ id +" with params: "+ params) */
paramsObj = eval( '('+params+')' );
gapi.plusone.render(id, paramsObj );
}
// params is here just for a reference to simulate what will come from gwt
params = '{href:"http://1vu.fr", size:"tall"}';
</script>
</head>
<body>
taken from http://jsfiddle.net/JQAdc/
<div id="gplus" />
<button onclick="gPlusBtn('gplus', params)">show!</button>
</body>
</html>
Then you can call a native method to trigger the button display on Activity start (if you're using MVP).
protected native void plusOneButton(String id, String params) /*-{
$wnd.gPlusBtn(id, params);
}-*/;
You can have multiple buttons with different urls, that's why id is left as a parameter.
NOTE: for me the raw HTML works on localhost, but the GWT version. I have to deploy to the server to be able to see the results

Wicket - Add body tag attribute

I'm stuck -
I need to have a Wicket Panel be able to add a class attribute to the <body> tag of whatever page it's on.
Example usage:
Java:
add(new SpecialSidebarComponent("sidebar"));
Generated HTML:
<body class="sidebar">
...
<div id="sidebar">My Wicket Panel</div>
...
</body>
I cannot add a wicket:id and make the body a Wicket component, because this makes it very difficult to add components to a page in the big page hierarchy I have, and it still also doesn't easily allow for a Panel to modify the body attribute.
I thought BodyTagAttributeModifier may be for this, but apparently it is for something else and cannot get it to function ( Wicket: how to use the BodyTagAttributeModifier class? )
Any helpful ideas?
Update:
In looking at it, it appears the BodyTagAttributeModifier class is only for a Panel's parent tag, not the Page's <body> tag:
Example (Scala syntax):
class Home extends WebPage {
add(new Sidebar("sidebar"))
}
class Sidebar(id: String) extends Panel(id) {
add(new BodyTagAttributeModifier("class", true, new Model("layout-class"), getParent))
}
Template:
<html>
<body>
<div wicket:id="sidebar">Sidebar</div>
</body>
</html>
Rendered:
<html>
<body>
<div class="layout-class">
<h1>Hello World!</h1>
</div>
</body>
</html>
Very confusing name IMHO. Doesn't solve the issue but at least makes more sense.
I personally think the Javascript option is the cleanest for this specific case. However, your comment about add(Component...) being final leads me to believe that you might be interested in the setTransparentResolver(true) method. Here's how it works...
BasePage.html
<body wicket:id="body">
<div wicket:id="panel" />
</body>
BasePage.java
public class BasePage extends Page {
public String bodyClass = "";
public BasePage() {
super();
WebMarkupContainer bodyContainer = new WebMarkupContainer("body");
bodyContainer.setTransparentResolver(true);
bodyContainer.add(new SimpleAttributeModifier("class", new PropertyModel<String>(this, "bodyClass")));
}
}
MyPage.java (extends BasePage)
public class MyPage extends BasePage {
public MyPage() {
super();
add(new SidebarPanel("panel"));
super.bodyClass = "sidebar";
}
}
Even though you are not adding the SidebarPanel directly to the bodyContainer in the BasePage, it will still work out because of setTransparentResolver(true).
For your simple case, go with the Javascript. For the general issue of feeling constrained by subclasses not being able to fit inside containers, be aware of transparent resolving.
If you really can't give the <body> tag a wicket:id (I'll assume you don't have a BasePage that every, or almost every, other page extends in which to abstract this), it'll be not possible to know at page render time (when that <body> tag is rendered) what class to append to it, it will be simply copied as is from your HTML to the output.
You could achieve the same via javascript, however. Make your Panel implement IHeaderContributor and use IHeaderResponse.renderOnDomReadyJavscript().
public abstract class SpecialSidebarComponent(String id) extends Panel
implements IHeaderContributor {
.....
public void renderHead(IHeaderResponse response){
String javascript = "document.body.setAttribute('class', 'sidebar');";
response.renderOnDomReadyJavascript(javascript);
}
....
}
I think you were on the right track with BodyTagAttributeModifier, at least according to JavaDoc. The compilation problems in the linked article stem from the use of a non-existing Constructor...
in SpecialSidebarComponent you should be able to do this:
add(new BodyTagAttributeModifier("class", Model.of("sidebar"), this));
Can't try this right now because I'm not at my development computer...