Map tab key to indent and shift+tab to outdent in TinyMCE (in Wicket)

Today’s post is about changing the behavior of the TinyMCE implementation in the wicket stuff library. In this library TinyMCE functionality can be implemented by just adding the TinyMCEBehaviour to the wicket component TextArea and calling the behavior’s constructor with an instance of TinyMCESettings, where you can set all kind of parameters.

Generally very content with our implementation, our customer wanted a way to define pre-formatted text blocks to use in documents at a later point. For ease of use, pressing the tab key should indent the text and shift+tab should revert the effect = outdent the current line. Although the advanced edit settings showed indent/outdent buttons we also wanted it to work when the buttons aren’t shown, in forms where space is precious for example. After some google searches I found this post (cached google version), about how to execute TinyMCE functionality in javascript and this stackoverflow answer, about where to put this info.

The solution, which works pretty well for us, was to insert a method in our TinyMCE class, which just adds the following function to the settings instance.

public static TinyMCESettings addTabFunctionality(TinyMCESettings settings) {
settings.addCustomSetting("setup : function(ed) { " +
"ed.onKeyDown.add(function(ed, e) { " +
"if(e.keyCode == 9) {" +
"if(e.shiftKey) {" +
"ed.execCommand('Outdent');" +
"}else{" +
"ed.execCommand('Indent');" +
"}" +
"e.preventDefault();" +
"return false;" +
"}" +
"});" +
"}");
return settings;
}

The addCustomSetting() method adds code to the init() function created by the TinyMCE addon and in the javascript code we listen for keydown in the textarea. If keycode equals ’9′ (tab) we check if shift is also pressed, if so an outdent action is performed using execCommand(‘Outdent’), if not, an indent is executed. By calling preventDefault() afterwards, the default action of the tab key is prevented – in our case it just was a 4 space-tab, which wasn’t written to the created html code. Calling the TinyMCE indent and outdent commands, padding is added to the affected line’s <p> tag (30px per tab) so the format can be saved to a database, without loosing the tabbed white-spaces.

Hope this helps someone, have a nice weekend! Until next time, feedback’s very welcome!

Posted in Javascript, Wicket | Tagged , , , , , , | Leave a comment

Running cron jobs on Raspberry Pi in Raspbmc

Here’s another little tutorial especially for people new to raspberry pi or linux in general (such as myself). Cron jobs are used to execute specific actions at pre-configured times. These actions can be executing scripts, writing data to a file, etc. (would be glad to hear of stuff you do with cron jobs in the comment section ;) )

In my specific case I needed a script to map my changing external ip address at home to the domain I specified for my raspberry to have access to it when I’m away. Big thanks for all the help to my good friend Thomas for domain hosting and tipps on how to get this to work! Now let’s get to it!

  1. Activate cron jobs in Raspbmc
    Per default running cron jobs is deactivated in Raspbmc and there are two ways to activate them.
    - In the Raspbmc GUI under Programs Raspbmc Settings -> System Configuration -> Service Management -> Cronjob Scheduler
    - Via SSH/FTP by modifying sys.service.cron value to “true” the settings file under /home/<your_username>/.xbmc/userdata/addon_data/script.raspbmc.settings/settings.xml – for more infos on changing settings via SSH / FTP, check my latest blog post
  2. Configure your ‘crontab’
    All cron jobs are defined in this file and you can specify multiple of them, each on its own line – to edit  your crontab in your default text editor, type ~$ crontab -e in the console. By using ~$ crontab -l the content is shown.
  3. Write your cronjob
    The syntax isn’t too easy to understand in the beginning, but there are tools online, which can help you write your (first) cron jobs. In my case the cron job looks like this:
    20,40 * * * * sh /dns_update.sh
    Every hour at minute xx:20 and xx:40 the dns_update.sh script in the root directory of my raspberry is executed, which just calls a magic dns mapping domain via wget.
    Especially in the beginning it’s a good idea to add a test job, which executes every minute and only helps to see if your cron configuration is set up properly. I use the following:
    * * * * * echo “crontest $(date) $(whoami)” >> /tmp/crontest.txt
    This just writes the current date and the current user to the specified textfile.
    Below is a screenshot of my current crontab:
    Screen Shot 2013-04-05 at 11.48.22 PM
  4. Control the cron service
    In order to get your cron jobs to run, the cron service must be active. The following commands let you control the cron service:
    ~$ /etc/init.d/cron stop
    ~$ /etc/init.d/cron start
    ~$ /etc/init.d/cron restart
    These commands will probably need a leading ‘sudo‘ – just check your console output. To quickly repeat your last command with leading sudo type ‘sudo !!‘.
  5. Check if your cron jobs are running
    If you also specified a test cron job like the one above, you can test if it’s working by printing the latest contents of the text file to your console. This can be done by using the ‘tail’ command and the ’-f‘ parameter updates the output as new content is added to the file. See below screenshot for example output:
    Screen Shot 2013-04-06 at 12.00.48 AM

And… That’s it! Thanks for reading, hope it helps someone, glad for every kind of feedback! Bye!

Posted in Raspberry Pi / Raspbmc | Tagged , , , , , , , , , , , | Leave a comment

Change Audiooutput mode and other settings in Raspbmc via FTP / SSH / command line

As i couldn’t find a proper guide to editing the settings of the raspbmc os via command line/ssh or ftp, here are my findings about it. As I’m pretty new to linux, there may be some faster / more efficient ways to do this (e.g. editing the setting files via nano/vi or even writing scripts to change certain settings) but for me the following works pretty well as for now. If you have some addition / comment please share them in the section below or contact me elsewhere, tia!

If you’re new to raspbmc the FAQ in the official wiki are definitely worth checking out. Here you find the default logon information (user: pi – pw: raspberry), the commands to stop and start xbmc (used in this guide) and many other interesting infos.

  1. Connect to your raspberry pi via FTP and/or SSH (i use FileZilla and the Mac OSX Terminal to do this – any other ftp/ssh client will also do)
  2. Navigate to /home/<username (default ‘pi’)>/.xbmc/userdata/guisettings.xml and open or download it. As you can see in the screenshot, I use Filezilla’s context menu to ‘View/Edit’ the remote file in my default text editor.
    Screen Shot 2013-03-30 at 2.18.21 PM
  3.  Look for the <mode> tag inside <audiooutput> tag or any other setting you want to change and change it to the value you need. For switching audio modes see the screenshot below.
    Screen Shot 2013-03-30 at 2.20.20 PM
  4. Save the settings file. Filezilla automatically detects changes to the local file and offers to upload the changed file – you can also delete the local copy in the process.
    Screen Shot 2013-03-30 at 2.20.45 PM
  5. Restart xbmc via SSH to apply the changes to your running raspberry pi – using the commands found in the FAQ mentioned above.
    Screen Shot 2013-03-30 at 2.21.42 PM

This already concludes my little guide for changing settings in raspbmc. For preferences set in the raspbmc settings addon, access the file /home/<your_username>/.xbmc/userdata/addon_data/script.raspbmc.settings/settings.xml – other than that the process is the same. Hope this helps someone – I’d be happy about every kind of feedback. Have a nice day! :)

Posted in Raspberry Pi / Raspbmc | Tagged , , , , , , , , , | Leave a comment

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!

Posted in CSS, Javascript, Wicket | Tagged , , , , , , , , , , , , , | Leave a comment

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 :)

Posted in CSS, Javascript | Tagged , , , , , , | Leave a comment

Welcome to wexoo.net

Welcome to wexoo’s organic pixel plant! On this site (sometime soon) you will find Java, Wicket, Android and Web Development snippets, which I personally find worth writing about and I come accross in my job or spare time and eventually info on some software I designed :) Stay tuned!

Posted in General | Leave a comment