Tag Archives: css

Building a custom FeedbackPanel in Wicket with Javascript

Today I’d like to present to you my first, very own tutorial about how to build a customized feedback-/notificationpanel in Wicket. I did this during my job a few weeks ago, because we were frustrated by the existing placement of our feedback panels. This one lets us show the notification anywhere on the page, while still using the Wicket built-in feedback system.

As far as the design goes, I managed to color the frame representing the most grave notification message (in our case just: info – warning – error) and color the distinct lines according to the level of feedback (blue for info, orange for warning, red for error). Sticking kinda to convention here 🙂

For every additional message the notification will stay half a second longer before fading out; this can be configured in the javascript function.

Implementation

Java

At first we will look at the java class of the notificationpanel, which extends FeedbackPanel to access all the built in methods of this class. If you want to know more details about the code please refer to the inline comments or just try it out, by copying it into your IDE.

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.Model;

public class NotificationPanel extends FeedbackPanel {

	private static final long serialVersionUID = 1L;
	private final String cssClass = "notificationpanel";
	private String additionalCSSClass = "notificationpanel_top_right";

	// Create a notifcation panel with the default additional class, specified as a field variable
	public NotificationPanel(String id) {
		super(id);

		init(id, additionalCSSClass);
	}

	// Create a notifcation panel with a custom additional class, overwriting the field variable
	public NotificationPanel(String id, String additionalCSSClass) {
		super(id);

		this.additionalCSSClass = additionalCSSClass;

		init(id, additionalCSSClass);
	}

	private void init(String id, String additionalCSSClass) {
		// set custom markup id and ouput it, to find the component later on in the js function
		setMarkupId(id);
		setOutputMarkupId(true);

		// Add the additional cssClass and hide the element by default
		add(new AttributeModifier("class", true, new Model<String>(cssClass + " " + additionalCSSClass)));
                add(new AttributeModifier("style", true, new Model<String>("opacity: 0;")));
	}

	/**
	 * Method to refresh the notification panel
	 * 
	 * if there are any feedback messages for the user, find the gravest level, 
	 * format the notification panel accordingly and show it
	 * 
	 * @param target
	 *            AjaxRequestTarget to add panel and the calling javascript function
	 */
	public void refresh(AjaxRequestTarget target) {

		// any feedback at all in the current form?
		if (anyMessage()) {
			int highestFeedbackLevel = FeedbackMessage.INFO;

			// any feedback with the given level?
			if (anyMessage(FeedbackMessage.WARNING))
				highestFeedbackLevel = FeedbackMessage.WARNING;
			if (anyMessage(FeedbackMessage.ERROR))
				highestFeedbackLevel = FeedbackMessage.ERROR;

			// add the css classes to the notification panel, 
			// including the border css which represents the highest level of feedback
			add(new AttributeModifier("class", true,
                                 new Model<String>(cssClass
                                           + " " + additionalCSSClass
                                           + " notificationpanel_border_" + String.valueOf(highestFeedbackLevel))));

			// refresh the panel and call the js function with the panel markup id 
			// and the total count of messages
			target.addComponent(this);
			target.appendJavascript("showNotification('" + getMarkupId() + "', "
					+ getCurrentMessages().size() + ");");
		}
	}

	/**
	 * Returns css class for the single rows of the panel
	 * 
	 * @see org.apache.wicket.markup.html.panel.FeedbackPanel#getCSSClass(org.apache.wicket.feedback.FeedbackMessage)
	 */
	@Override
	protected String getCSSClass(FeedbackMessage message) {
		return "notificationpanel_row_" + message.getLevelAsString();
	}
}

Javascript

The javascript function uses the jquery fading methods to show and hide the notification in a nice manor. Here you can configure the time intervals and the opacity of the fading effects.

function showNotification(componentId, messagecount){
	
	timeout = 5000 + (messagecount * 500);
	
	$('div#' + componentId).fadeTo('normal', 1.0);
	
	setTimeout("$('div#" + componentId + "').fadeTo('normal', 0.6)", timeout);
	
	timeout += 2000; 
	
	setTimeout("$('div#" + componentId + "').fadeOut('normal')", timeout);
}

CSS

The css classes used. The class notifcationpanel defines some standard properties like bg color, padding, rounded corners (css3 border-radius) and position: fixed to maintain an absolute position and don’t scroll with the content. .notificationpanel_xxx are the classes used to add as the additionalCSSClass to the NotificationPanel, here you can add your custmized css class. .notificationpanel_border/row_xxx defines the border and colors of the panel and the distinct messages, configure as you please.

.notificationpanel {
background-color: #fff;
min-width:150px;
padding: 3px;
position: fixed;
z-index:999;
border-radius:8px;
}

.notificationpanel_bottom_left {
bottom: 100px;
left: 30px;
}

.notificationpanel_bottom_detail_form {
top: 540px;
right: 30px;
}

.notificationpanel_bottom_right {
bottom: 100px;
right: 30px;
}

.notificationpanel_top_right {
top: 15px;
right: 30px;
}

/* info */
.notificationpanel_border_200 {
	border: 3px solid #0053a0;
	box-shadow: 0px 0px 5px #000;
}

.notificationpanel_row_INFO {
	color: #0053a0;
}

/* warning */
.notificationpanel_border_300 {
	border: 3px solid #FF9900;
	box-shadow: 0px 0px 6px #000;
}

.notificationpanel_row_WARNING {
	color: #FF9900;
}

/* error */
.notificationpanel_border_400 {
	border: 3px solid #CC3300;
	box-shadow: 0px 0px 7px #000;
}

.notificationpanel_row_ERROR {
	color: #CC3300;
}

Usage

HTML

To use the NotificationPanel just define a div container with a wicket:id of your choosing and watch the hierarchy to add it to the right component (works best inside a form).

Java

After that you can create the notificationPanel in your java code, be sure to create the variable as global as you need it or pass it on as a parameter, to the parts where you want to use it.

//leave out second parameter if you like to create a panel which uses the additional css class defined in the NotificationPanel class variable
NotificationPanel notificationPanel = new NotificationPanel("notificationPanelId", "notificationpanel_bottom_detail_form");
add(notificationPanel);

When all is set up, you can use the panel quite like the standard Wicket FeedbackPanel. Just define your info/warning/error message and, here’s the small difference, instead of just adding the panel to the AjaxRequestTarget, call the refresh method of the panel. Here you go!

error("Random error message!!!");
notificationPanel.refresh(ajaxRequestTarget);

I hope you’ve enjoyed my first tutorial and I hope I can help somebody, dealing with a similar problem as we have! If you like this post, please consider subscribing to my feed or following me in any other way; see Follow Me! on the right for your choice 😉

I’d be also very happy, if you drop me a line in the comments or contact me any other way, be it for criticism, a simple comment, thanks, suggestions for improvement, or else! Thank you for reading!

Update 10/21/2011: – Refactored the AttributeModifiers, which weren’t part of stock wicket. I tested it in another project with the current code, works now!

CSS Rolling Example with CSS3 and JQuery (Originally on queness.com)

Recently I did some work with javascript in my job and as I have never worked with it before, right now I’m pretty interested in learning more about the capabilities of it. While doing some research for my work related problem, I stumbled over the awesome blog Queness. On this site you find many design related topics and tutorials for web designers. They really deserve the credit for the post here but as I found some errors in the tutorial and I added some comments to make the javascript part easier to understand, I’d like to provide my own version of their tutorial.

Click to see live demo

Preparation

  • Download JQuery Easing Plugin (A minified version can be found here)
  • Create files index.html and main.css and put the downloaded/created javascript file (‘jquery.easing.min.js’) into the same folder
  • Optional: If you want to test the example offline, download the JQuery javascript file here, put it in the same folder as the files above and change the script tag in index.html

HTML / Javascript

Most of the action happens in the html page of the example (just copy this to your index.html file, for now use ‘view plain’ and copy code, I’m working on getting ‘copy to clipboard’ to work)

Via the js document ready function the on click behaviour is added to the later defined div containers. For a more detailed description of the javascript actions see the comments.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="main.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/
ajax/libs/jquery/1.6.2/jquery.min.js"></script> /* or src="jquery.min.js" */
<script type="text/javascript" src="jquery.easing.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
	$(".rectangle").click(function()
	{
		/* in 500 ms transform rectangle to square with 100px length */
		$(this).animate({width:'100px',height:'100px'}, 500, 'linear', function()
		{
			/* add class circle-label-rotate -> start spinning animation and repeat infinitely */
			$(this).addClass('circle-label-rotate')
			/* add class circle -> transform to circle and set background to grey */
			.addClass('circle')
			/* write 'Bye' in circle */
			.html('<div class="innertext">Bye</div>')
			/* move circle 510px to the left and fade it out */
			.animate({"opacity":"0","margin-left":"510px"},1500);
			
			/* move up the rest of the layout and remove placeholder of currently clicked element */
			/* 2.param = easing -> more info: http://gsgd.co.uk/sandbox/jquery/easing/*/
			$(this).slideUp('slow','linear');
		})
	})
});
</script>

<title>CSS Sliding Example</title>
</head>
<body>
	<div class='rectangle'> 1</div>
	<div class='rectangle'> 2</div>
	<div class='rectangle'> 3</div>
</body>
</html>

CSS

Copy these css classes to your main.css class.

.rectangle
{
	height:100px;
	width:500px;
	border:dashed 1px #000;
	margin-top:10px;
}

.circle-label-rotate
{
	-webkit-animation-name: rotateThis;
	-webkit-animation-duration:2s;
	-webkit-animation-iteration-count:infinite;
	-webkit-animation-timing-function:linear;
}

@-webkit-keyframes rotateThis 
{
	from {-webkit-transform:scale(1) rotate(0deg);}
	to {-webkit-transform:scale(1) rotate(360deg);}
}

.circle
{
	border-radius: 50px; // Chrome & IE9
	-moz-border-radius: 50px; // Firefox
	-webkit-border-radius: 50px; // Safari 
	height:100px;
	width:100px;
	background:#dedede;
}

.innertext
{
	text-align: center;
}

Finally just run index.html in your favourite browser and click on the rectangles to see the effect. Thanks for reading and please share any thoughts 🙂