Search
Categories
Ad

Archive for June, 2009

g++ on RHEL 5

Wednesday, June 17th, 2009

Problem

g++ is not installed on your Redhat EL 5 at default.

Solution

Try;

% yum install gcc-c++ compat-gcc-*
% which g++

If you still not find g++, maybe g++ is saved as g++32 in /usr/bin. If so, create a symbolic link to g++32.

% ln -s /usr/bin/g++32 /usr/bin/g++

Fail to compile Ruby1.9 on VPS because of the RAM size.

Wednesday, June 17th, 2009

Problem

You want to compile ruby1.9, but failed with errors:

gcc -I. -I.ext/include/i686-linux -I./include -I. -D_FILE_OFFSET_BITS=64  -DONIG_ENC_REGISTER=rb_enc_register -fPIC  -O2 -g -Wall -Wno-parentheses  -o enc/trans/gb18030.o -c ./enc/trans/gb18030.c
virtual memory exhausted: Cannot allocate memory
make[1]: *** [enc/trans/gb18030.o] Error 1
make[1]: Leaving directory `/home/roiadmin/tmp/ruby-1.9.1-p129'
make: *** [trans] Error 2

You maybe tried changing ulimit values or add gcc-min-heapsize parameters, but all failed in vain.

Solution

The best way to do so is remove gb18030.c from compilation packages. Hope you are not planning to use Chinese GB18030 encoded-strings in Ruby.
The compile instructions are written in “enc.mk”. So all you need to do is delete all lines about gb18030 in “enc.mk”.

If you are compileing 1.9.1-p129, you can use this patch file.

*** enc.mk.org	Wed Jun 17 21:36:49 2009
--- enc.mk	Wed Jun 17 21:38:44 2009
***************
*** 79,85 ****
  	  enc/euc_kr.$(OBJEXT) \
  	  enc/euc_tw.$(OBJEXT) \
  	  enc/gb2312.$(OBJEXT) \
- 	  enc/gb18030.$(OBJEXT) \
  	  enc/gbk.$(OBJEXT) \
  	  enc/iso_8859_1.$(OBJEXT) \
  	  enc/iso_8859_2.$(OBJEXT) \
--- 79,84 ----
***************
*** 113,119 ****
  	 $(ENCSODIR)/euc_kr.$(DLEXT) \
  	 $(ENCSODIR)/euc_tw.$(DLEXT) \
  	 $(ENCSODIR)/gb2312.$(DLEXT) \
- 	 $(ENCSODIR)/gb18030.$(DLEXT) \
  	 $(ENCSODIR)/gbk.$(DLEXT) \
  	 $(ENCSODIR)/iso_8859_1.$(DLEXT) \
  	 $(ENCSODIR)/iso_8859_2.$(DLEXT) \
--- 112,117 ----
***************
*** 147,153 ****
  TRANSCSRCS = enc/trans/big5.c \
  	     enc/trans/chinese.c \
  	     enc/trans/escape.c \
- 	     enc/trans/gb18030.c \
  	     enc/trans/gbk.c \
  	     enc/trans/iso2022.c \
  	     enc/trans/japanese.c \
--- 145,150 ----
***************
*** 161,167 ****
  	    enc/trans/big5.$(OBJEXT) \
  	    enc/trans/chinese.$(OBJEXT) \
  	    enc/trans/escape.$(OBJEXT) \
- 	    enc/trans/gb18030.$(OBJEXT) \
  	    enc/trans/gbk.$(OBJEXT) \
  	    enc/trans/iso2022.$(OBJEXT) \
  	    enc/trans/japanese.$(OBJEXT) \
--- 158,163 ----
***************
*** 175,181 ****
  	   $(ENCSODIR)/trans/big5.$(DLEXT) \
  	   $(ENCSODIR)/trans/chinese.$(DLEXT) \
  	   $(ENCSODIR)/trans/escape.$(DLEXT) \
- 	   $(ENCSODIR)/trans/gb18030.$(DLEXT) \
  	   $(ENCSODIR)/trans/gbk.$(DLEXT) \
  	   $(ENCSODIR)/trans/iso2022.$(DLEXT) \
  	   $(ENCSODIR)/trans/japanese.$(DLEXT) \
--- 171,176 ----
***************
*** 267,276 ****
  	@$(MAKEDIRS) "$(@D)"
  	$(LDSHARED) -o $@ enc/gb2312.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
 
- $(ENCSODIR)/gb18030.$(DLEXT): enc/gb18030.$(OBJEXT)
- 	@$(MAKEDIRS) "$(@D)"
- 	$(LDSHARED) -o $@ enc/gb18030.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
- 
  $(ENCSODIR)/gbk.$(DLEXT): enc/gbk.$(OBJEXT)
  	@$(MAKEDIRS) "$(@D)"
  	$(LDSHARED) -o $@ enc/gbk.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
--- 262,267 ----
***************
*** 383,392 ****
  	@$(MAKEDIRS) "$(@D)"
  	$(LDSHARED) -o $@ enc/trans/escape.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
 
- $(ENCSODIR)/trans/gb18030.$(DLEXT): enc/trans/gb18030.$(OBJEXT)
- 	@$(MAKEDIRS) "$(@D)"
- 	$(LDSHARED) -o $@ enc/trans/gb18030.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
- 
  $(ENCSODIR)/trans/gbk.$(DLEXT): enc/trans/gbk.$(OBJEXT)
  	@$(MAKEDIRS) "$(@D)"
  	$(LDSHARED) -o $@ enc/trans/gbk.$(OBJEXT) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
--- 374,379 ----
***************
*** 451,460 ****
  	-@$(MAKEDIRS) "$(@D)"
  	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/gb2312.c
 
- enc/gb18030.$(OBJEXT): $(encsrcdir)/gb18030.c
- 	-@$(MAKEDIRS) "$(@D)"
- 	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/gb18030.c
- 
  enc/gbk.$(OBJEXT): $(encsrcdir)/gbk.c
  	-@$(MAKEDIRS) "$(@D)"
  	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/gbk.c
--- 438,443 ----
***************
*** 567,576 ****
  	-@$(MAKEDIRS) "$(@D)"
  	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/trans/escape.c
 
- enc/trans/gb18030.$(OBJEXT): $(encsrcdir)/trans/gb18030.c
- 	-@$(MAKEDIRS) "$(@D)"
- 	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/trans/gb18030.c
- 
  enc/trans/gbk.$(OBJEXT): $(encsrcdir)/trans/gbk.c
  	-@$(MAKEDIRS) "$(@D)"
  	$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(encsrcdir)/trans/gbk.c
--- 550,555 ----

Enjoy!

share repositories in windows with osx using “git push”

Wednesday, June 17th, 2009

Problem

You have a git repos in Windows XP, and you want to share that with your MacOSX machine. The easiest way seems git clone in MacOSX. However, my win repos are in D drive and I did not find out how to write the repos path. I did

git clone tomoya@windows:d:\home\git.git
git clone tomoya@windows:d:\\home\\git.git
git clone tomoya@windows:d:/home/git.git
git clone tomoya@windows:"d:/home/git.git"

but all failed in vain.

Thus, I changed my mind to use git push from Windows.

Solution

SSH server on Windows

First, if you have not installed cygwin, or any SSH server for Windows, install freeSSHd. This programs runs on Windows as a SSH server.

create repository in MacOSX

[MacOSX]
tomoya@macosx% cd ~/Workspace/git
tomoya@macosx% git init

Add remote repository

[Windows]
D:\home\git> git remote add origin tomoya@macosx:/Users/tomoya/Workspace/git

Try connectiing to remote

[Windows]
D:\home\git> git remote show origin

Then I got a error as

Permission denied (publickey,keyboard-interactive).
fatal: The remote end hung up unexpectedly

This is because my MacOSX requires key authentication. So, I specified pub.key files just by creating config file in %HOME%/.ssh/.

[Windows]
D:\home\git> notepad "%HOME%\.ssh\config"

and, type

Host 192.168.1.21
  User tomoya
  Port 22
  Hostname 192.168.1.21
  IdentityFile C:/id_rsa
  TCPKeepAlive yes
  IdentitiesOnly yes

Try connecting again.

[Windows]
D:\home\git> git remote show origin
zsh: command not found: git-upload-pack
fatal: The remote end hung up unexpectedly

Great. I had these errors because my default login shell on MacOSX is zsh and my zsh does not know where git-upload-pack command is. Check whether git-upload-pack is installed correctly.

[MacOSX]
tomoya@macosx% which git-upload-pack
/opt/local/bin/git-upload-pack

OK. Now check if i have .zshenv file in your home directory.

[MacOSX]
tomoya@macosx% cat ~/.zshenv
cat: /Users/tomoya/.zshenv: No such file or directory

I do not. So I made a symbolic link to .zshenv.

[MacOSX]
tomoya@macosx% ln -s ~/.zshrc ~/.zshenv

More detailed infomation about .zshrc and .zshenv can be found at here: http://zsh.dotsrc.org/Intro/intro_3.html.
Try connecting fot the third time.

[Windows]
D:\home\git> git remote show origin
* remote origin
  URL: tomoya@192.168.1.21:/Users/tomoya/Workspace/git
  HEAD branch: master
  Remote branch:
    master tracked
  Local ref configured for 'git push':
    master pushes to master (up to date)

Hoora! We made it. Ok, move on to next task.

Push to OSX

[Windows]
D:\home\git> git push origin master

And on MacOSX,

[MacOSX]
tomoya@macosx% ls ~/Workspace/git

If you see no files in this directory, this is because pushed files are deleted temporarily, so revert all the files as

[MacOSX]
tomoya@macosx% git reset --hard HEAD

That’s all. Now you have the second repos in your Mac OSX.

Ruby Sinatra application on Google App Engine Java

Wednesday, June 17th, 2009

This article is all about what I have done to make my first Sinatra application on Google’s App engine/Java aka GAE. As you know, Sinatra is a light web application framework for Ruby. We can run Sinatra on GAE because GAE has started to support Java since April 2009 and there existed a Java implementation of Ruby called JRuby.

Before proceeding, you are sure that you already have a valid account for GAE. Otherwise, hurry up to register your account at here.

OK, now you are ready and let’s get started!

Install JRuby

First, download a JRuby package using git. If you are unfamiliar with Git, tutorials and articles on github, including screencasts and podcasts are your good introduction.

Installation of git on Ubuntu is as easy as

% apt-get install git-core

If you are using other operating systems, check http://github.com/guides/home.

To install JRuby, type

% git clone git://kenai.com/jruby~main

Do not type jruby-main. jruby~main is correct.

Moving to jruby~main directory, start compiling.

% cd jruby~main
% ant
% ant jar-complete

Check the jruby version with

% bin/jruby –version
jruby 1.4.0dev (ruby 1.8.6p287) (2009-06-16 6586) (Java HotSpot(TM) Client VM 1.5.0_16) [i386-java]

Install Sinatra and related gems

Check the gem version with

% bin/jruby –S gem –version
1.3.3

To install rubygems for your new jruby, try

% bin/jruby –S gem install rake sinatra wabler mongrel
JRuby limited openssl loaded. gem install jruby-openssl for full support.
<a href="http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL">http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL</a>
Successfully installed rake-0.8.7
Successfully installed rack-1.0.0
Successfully installed sinatra-0.9.2
Successfully installed warbler-0.9.13
Successfully installed gem_plugin-0.2.3
Successfully installed mongrel-1.1.5-java
6 gems installed

Did you see OpenSSL messages, too? You can leave it for now.

Install JRuby-Rack

Get a copy of jruby-rack from github.

% cd ../ # only if you are still in jruby~main directory
% git clone git://github.com/nicksieger/jruby-rack.git
% cd jruby-rack
% ../jruby\~main/bin/jruby -S rake SKIP_SPECS=true

Be careful not to forget to add “SKIP_SPECS=true” when you perform rake command in jruby-rack. Without it, rake will fail.

Create Sinatra Appcalition

Now, let’s create a new Sinatra application. First make a directory for our first app.

% mkdir myway-app

Make directories

% mkdir views public config lib

Create files

1. config.ru

require 'rubygems'
require 'sinatra'
root_dir = File.dirname(__FILE__)
set :environment, :production
set :root, root_dir
set :app_file, File.join(root_dir, 'app.rb')
disable :run
require 'app'
run Sinatra::Application

2. app.rb

require 'rubygems'
require 'sinatra'
 
get '/' do
  "Hello from Sinatra running on Java!"
end

3. appengine-web.xml

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>live-ch</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

4. config/warble.rb

Warbler::Config.new do |config|
  config.dirs = %w(lib views public)
  config.includes = FileList["appengine-web.xml", "app.rb"]
  config.staging_dir = 'war'
  config.java_libs = []
  config.gems = ['sinatra']
  config.gem_dependencies = true 
  config.webxml.booter = :rack 
end

For a test run,

% ruby app.rb
== Sinatra/0.9.2 has taken the stage on 4567 for development with backup from Mongrel

Go to http://localhost:4567/, and you will see a string message that sinatra is running. OK, press Ctrl+C to stop the server.

Setup for GAE

You need to download GAE SDK for Java from here. The latest version at this moment is version 1.2.1, released on May 13, 2009.

After the download is finished, we need to copy appengine-java-sdk-1.2.1/lib/user/appengine-api-1.0-sdk-1.2.1.jar to Sinatra Application’s lib directory.

% cp ~/Downloads/appengine-java-sdk-1.2.1/lib/user/appengine-api-1.0-sdk-1.2.1.jar lib/

Also, we need to copy jruby-rack jars to lib directory.

% cp ../jruby-rack/target/jruby-rack-0.9.5-SNAPSHOT.jar lib/

Next, we need to copy jruby itself in lib directory, and split it into a two files because the original jruby-complete.jar is too big to use in GAE.

% cp ../juby~main/lib/jruby-complete.jar lib/

Then, create a shellscript called split-jar.sh

#!/bin/sh
 
rm -rf jruby-core.jar
rm -rf ruby-stdlib.jar
rm -rf tmp_unpack
mkdir tmp_unpack
cd tmp_unpack
jar xf ../jruby-complete.jar
cd ..
mkdir jruby-core
mv tmp_unpack/org jruby-core/
mv tmp_unpack/com jruby-core/
mv tmp_unpack/jline jruby-core/
mv tmp_unpack/jay jruby-core/
mv tmp_unpack/jruby jruby-core/
cd jruby-core
jar cf ../jruby-core.jar .
cd ../tmp_unpack
jar cf ../ruby-stdlib.jar .
cd ..
rm -rf jruby-core
rm -rf tmp_unpack
rm -rf jruby-complete.jar

And run

% sh split-jar.sh

Try “ls” to see that you have “jruby-core.jar” and “jruby-stdlib.jar” instead of “jruby-complete.jar”.

Now it is time to create “war” files with warbler.

% ../jruby~main/bin/jrruby –S warble

Run at localhost.

% ../appgengine-java-sdk-1.2.1/bin/dev_appserver.sh --port=18080 war

If you have no error, open http://localhost:18080/ with your own browser. you will see the messages.

Deployment

You need to overwrite APPLICATION-ID with your own in appengine-web.xml. When finished, create war files again as

% ../jruby~main/bin/jrruby –S warble

Then running deployment script

% ../appgengine-java-sdk-1.2.1/bin/appcfg.sh update war

If you run this script first time, you will be prompted to input your email address and password. Input your email of your GAE account correctly. After a while, the script will be finished, and you can see your Sinatra/GAE apps at http://{YOUR-APPLICATION-ID}.appspot.com.

 

This is all. Enjoy making Ruby web application on GAE!

Dump YAML Strings with UTF-8 multibyte characters in Ruby

Tuesday, June 16th, 2009

Problem

You want to dump your Ruby object to YAML-formatted file, but your object contains UTF-8 multibyte characters. In this situation, original yaml dumper will output in a human-unfriendly format like

  - !binary |
   5a6X6LC35bKs

Solution

The easiest way to solve is to use ya2yaml.

 sudo gem install ya2yaml

Then, in your source code,

open("save.yml", "w") do |f| 
 f.write multiByteObj.ya2yaml
end

Export Selected Area from Illustrator

Monday, June 15th, 2009

Problem

You want to export some parts of artwork from Illustrator.

Solution


  1. Choose Trimarea tool (Shift+O) to create a Trim area.
  2. Select the artwork elements you want to export.
  3. Adjust the trimarea with your mouse if you need to.
  4. Choose File -> Print to show up Printer settings dialog.
  5. In the Dialog, go to Setup and change the value of Trimming to Trimarea.
  6. Click Finish to close the dialog.
  7. Choose File -> Export and select the format you want to export as.

If you choose to export your artwork as PNG format, you will see a preview image. You can check you just created a right trimarea.

gisty for gist and gisty for Ruby1.9.1

Sunday, June 14th, 2009

Introduction

gist is a simple web service by github for posting and sharing your cool code snippets. gisty is a command-line client for gist.

Installation of gisty

sudo gem install nokogiri
sudo gem sources -a http://gems.github.com
sudo gem install swdyh-gisty

Usage

Posting a source code is as easy as

 gisty post hello.c world.c

Also, you can ‘clone’ all your code snippets.

 gisty sync

For more information, type

 gisty help





And the problem is…

Problem

gisty does not work with Ruby1.9.1.

Solution

I made a forked version of gisty on github repos. Soon, you will be able to download this version

sudo gem install tomoya55-gisty

Notice: you cannot install tomoya55-gisty at this moment. I am now investigating what is going on on my gems. Thank you.

Copy File Paths from Finder

Saturday, June 13th, 2009

Problem

You want to copy the Path of file(s) shown in Finder.

Solution

090613-0001

CopyPath is a grat solution for our problem. After downloading CopyPath.zip, unzip it and copy the app to Application direcotry. Then drag the CopyPath Icon to Finder’s toolbar area. Now, you will see CopyPath button on your Finder.

When the button is clicked, the paths of files selected in Finder will be copied to your clipboard.

Thank you for nice application, David.

HTML Table height

Wednesday, June 10th, 2009

Problem

I want to set the height of table rows in HTML.

Solution

You can set the height attribute in TR tags.

50 not set
not set not set


<tr><td height="50px">50</td><td>not set</td></tr>



[NOTE]  Be careful. You cannot set the height attribute in TR.

jquery-in-place-editor Keeping-NewLine version.

Wednesday, June 10th, 2009

Problem

I am using jquery-in-place-editor plugin. Most of all, this plugin works nice. Except one point.
Newlines(n) are always ignored even if I use the ‘textarea’ input.

Solution

Here is the new version of jquery-in-place-editor plugin. I just added String#br2newline() function and changed to show $(element).html() when ‘textarea’ input is used. The original one showed $(element).text() in ‘textarea’, which always removes *ANY* html tags from the contents.

The scirpt can be downloaded from here.

/** 
 * Another In Place Editor - a jQuery edit in place plugin (Keeping-newline version)
 * 
 * 2009 NiceCabbage and Tomoya Hirano
 * 
 * License: BSD lincense.
 */
 
/*
 * Another In Place Editor - a jQuery edit in place plugin
 *
 * Copyright (c) 2009 Dave Hauenstein
 *
 * License:
 * This source file is subject to the BSD license bundled with this package.
 * Available online: {@link http://www.opensource.org/licenses/bsd-license.php}
 * If you did not receive a copy of the license, and are unable to obtain it,
 * email davehauenstein@gmail.com,
 * and I will send you a copy.
 *
 * Project home:
 * http://code.google.com/p/jquery-in-place-editor/
 *
 */
 
/*
 * Version 1.0.2
 *
 * bg_out (string) default: transparent hex code of background color on restore from hover
 * bg_over (string) default: #ffc hex code of background color on hover
 * callback (function) default: null function to be called when editing is complete; cancels ajax submission to the url param
 * cancel_button (string) default: <input type=”submit” class=”inplace_cancel” value=”Cancel”/> image button tag to use as “Cancel” button
 * default_text (string) default: “(Click here to add text)” text to show up if the element that has this functionality is empty
 * element_id (string) default: element_id name of parameter holding element_id
 * error (function) this function gets called if server responds with an error
 * field_type (string) “text”, “textarea”, or “select”; default: “text” The type of form field that will appear on instantiation
 * on_blur (string) “save” or null; default: “save” what to do on blur; will be overridden if $param show_buttons is true
 * original_html (string) default: original_html name of parameter holding original_html
 * params (string) example: first_name=dave&last_name=hauenstein paramters sent via the post request to the server
 * save_button (string) default: <input type=”submit” class=”inplace_save” value=”Save”/> image button tag to use as “Save” button
 * saving_image (string) default: uses saving text specify an image location instead of text while server is saving
 * saving_text (string) default: “Saving…” text to be used when server is saving information
 * select_options (string) comma delimited list of options if field_type is set to select
 * select_text (string)default text to show up in select box
 * show_buttons (boolean) default: false will show the buttons: cancel or save; will automatically cancel out the onBlur functionality
 * success (function) default: null this function gets called if server responds with a success
 * textarea_cols (integer) default: 25 set cols attribute of textarea, if field_type is set to textarea
 * textarea_rows (integer) default: 10 set rows attribute of textarea, if field_type is set to textarea
 * update_value (string) default: update_value name of parameter holding update_value
 * url (string) POST URL to send edited content
 * value_required (string) default: false if set to true, the element will not be saved unless a value is entered
 *
 */
 
jQuery.fn.editInPlace = function(options) {
 
	/* DEFINE THE DEFAULT SETTINGS, SWITCH THEM WITH THE OPTIONS USER PROVIDES */
	var settings = {
		url:				"",
		params:				"",
		field_type:			"text",
		select_options:		"",
		textarea_cols:		"25",
		textarea_rows:		"10",
		bg_over:			"#ffc",
		bg_out:				"transparent",
		saving_text:		"Saving...",
		saving_image:		"",
		default_text:		"(Click here to add text)",
		select_text:		"Choose new value",
		value_required:		null,
		element_id:			"element_id",
		update_value:		"update_value",
		original_html:		"original_html",
		save_button:		'<button class="inplace_save">Save</button>',
		cancel_button:		'<button class="inplace_cancel">Cancel</button>',
		show_buttons:		false,
		on_blur:			"save",
		callback:			null,
		callbackShowErrors: true,
		success:			null,
		error:				function(request){
                                alert("Failed to save value: " + request.responseText || 'Unspecified Error');
                            }
	};
 
	if(options) {
		jQuery.extend(settings, options);
	}
 
	/* preload the loading icon if it exists */
	if(settings.saving_image != ""){
		var loading_image = new Image();
		loading_image.src = settings.saving_image;
	}
 
	/* THIS FUNCTION WILL TRIM WHITESPACE FROM BEFORE/AFTER A STRING */
	String.prototype.trim = function() {
		return this.replace(/^\s+/, '')
							 .replace(/\s+$/, '');
	};
 
	/* THIS FUNCTION WILL ESCAPE ANY HTML ENTITIES SO "Quoted Values" work */
	String.prototype.escape_html = function() {
		return this.replace(/&/g, "&amp;")
							 .replace(/</g, "&lt;")
							 .replace(/>/g, "&gt;")
							 .replace(/"/g, "&quot;");
  	};
 
  	String.prototype.br2newline = function() {
		return this.replace(/<br\s*\/>/g, "\n")
					.replace(/<br\s*>/g, "\n");
  	};
 
	/* CREATE THE INPLACE EDITOR */
	return this.each(function(){
 
		if(jQuery(this).html() == "") jQuery(this).html(settings.default_text);
 
		var editing = false;
 
		//save the original element - for change of scope
		var original_element = jQuery(this);
 
		var click_count = 0;
 
		jQuery(this)
 
		.mouseover(function(){
			jQuery(this).css("background", settings.bg_over);
		})
 
		.mouseout(function(){
			jQuery(this).css("background", settings.bg_out);
		})
 
		.click(function(){
			click_count++;
 
			if(!editing)
			{
				editing = true;
 
				//save original text - for cancellation functionality
				var original_html = jQuery(this).html();
				var buttons_code  = (settings.show_buttons) ? settings.save_button + ' ' + settings.cancel_button : '';
 
				//if html is our default text, clear it out to prevent saving accidentally
				if (original_html == settings.default_text) jQuery(this).html('');
 
				if (settings.field_type == "textarea")
				{
					var use_field_type = '<textarea name="inplace_value" class="inplace_field" rows="' + settings.textarea_rows + '" cols="' + settings.textarea_cols + '">' + original_html.br2newline().trim().escape_html() + '</textarea>';
				}
				else if(settings.field_type == "text")
				{
					var use_field_type = '<input type="text" name="inplace_value" class="inplace_field" value="' +
											jQuery(this).text().trim().escape_html() + '" />';
				}
				else if(settings.field_type == "select")
				{
					var optionsArray = settings.select_options.split(',');
					var use_field_type = '<select name="inplace_value" class="inplace_field"><option value="">' + settings.select_text + '</option>';
						for(var i=0; i<optionsArray.length; i++){
							var optionsValuesArray = optionsArray[i].split(':');
							var use_value = optionsValuesArray[1] || optionsValuesArray[0];
							var selected = use_value == original_html ? 'selected="selected" ' : '';
							use_field_type += '<option ' + selected + 'value="' + use_value.trim().escape_html() + '">' + optionsValuesArray[0].trim().escape_html() + '</option>';
                        }
						use_field_type += '</select>';
				}
 
				/* insert the new in place form after the element they click, then empty out the original element */
				jQuery(this).html('<form class="inplace_form" style="display: inline; margin: 0; padding: 0;">' + use_field_type + ' ' + buttons_code + '</form>');
 
			}/* END- if(!editing) -END */
 
			if(click_count == 1)
			{
				function cancelAction()
				{
					editing = false;
					click_count = 0;
 
					/* put the original background color in */
					original_element.css("background", settings.bg_out);
 
					/* put back the original text */
					original_element.html(original_html);
 
					return false;
				}
 
				function saveAction()
				{
					/* put the original background color in */
					original_element.css("background", settings.bg_out);
 
                    var this_elem = jQuery(this);
 
					var new_html = (this_elem.is('form')) ? this_elem.children(0).val() : this_elem.parent().children(0).val();
 
					/* set saving message */
					if(settings.saving_image != ""){
						var saving_message = '<img src="' + settings.saving_image + '" alt="Saving..." />';
					} else {
						var saving_message = settings.saving_text;
					}
 
					/* place the saving text/image in the original element */
					original_element.html(saving_message);
 
					if(settings.params != ""){
						settings.params = "&" + settings.params;
					}
 
					if(settings.callback) {
						html = settings.callback(original_element.attr("id"), new_html, original_html, settings.params);
						editing = false;
						click_count = 0;
						if (html) {
							/* put the newly updated info into the original element */
							original_element.html(html || new_html);
						} else {
							/* failure; put original back */
							if(settings.callbackShowErrors)
							{
							    alert("Failed to save value: " + new_html);
							}
							original_element.html(original_html);
						}
					} else if (settings.value_required && (new_html == "" || new_html == undefined)) {
						editing = false;
						click_count = 0;
						original_element.html(original_html);
						alert("Error: You must enter a value to save this field");
					} else {
						jQuery.ajax({
							url: settings.url,
							type: "POST",
							data: settings.update_value + '=' + new_html + '&' + settings.element_id + '=' + original_element.attr("id") + settings.params + '&' + settings.original_html + '=' + original_html,
							dataType: "html",
							complete: function(request){
								editing = false;
								click_count = 0;
							},
							success: function(html){
								/* if the text returned by the server is empty, */
   								/* put a marker as text in the original element */
								var new_text = html || settings.default_text;
 
								/* put the newly updated info into the original element */
								original_element.html(new_text);
								if (settings.success) settings.success(html, original_element);
							},
							error: function(request) {
								original_element.html(original_html);
								if (settings.error) settings.error(request, original_element);
							}
						});
					}
 
					return false;
				}
 
				/* set the focus to the new input element */
				original_element.children("form").children(".inplace_field").focus().select();
 
				/* CLICK CANCEL BUTTON functionality */
				original_element.children("form").children(".inplace_cancel").click(cancelAction);
 
				/* CLICK SAVE BUTTON functionality */
				original_element.children("form").children(".inplace_save").click(saveAction);
 
                /* if cancel/save buttons should be shown, cancel blur functionality */
                if(!settings.show_buttons){
                    /* if on_blur is set to save, set the save funcion */
    				if(settings.on_blur == "save")
    					original_element.children("form").children(".inplace_field").blur(saveAction);
    				/* if on_blur is set to cancel, set the cancel funcion */
    				else
    					original_element.children("form").children(".inplace_field").blur(cancelAction);
                }
 
				/* hit esc key */
				$(document).keyup(function(event){
				    if (event.keyCode == 27) {
						cancelAction();
				    }
				});
 
                original_element.children("form").submit(saveAction);
 
			}/* END- if(click_count == 1) -END */
		});
	});
};

And the Server-side script example in Ruby.

cgi = CGI.new
print cgi.header
print cgi['update_value'].gsub( /\n/, '<br>' )

Enjoy it!