<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3896461559970632672</id><updated>2012-02-16T00:17:47.165-08:00</updated><title type='text'>Cochran Software</title><subtitle type='html'>This is a technical blog for Cochran Software.  Visit our website at &lt;a href="http://www.cochran-software.com"&gt;
www.cochran-software.com&lt;/a&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cochransoftware.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-5149994130579358457</id><published>2009-05-20T12:10:00.001-07:00</published><updated>2009-05-20T12:12:28.558-07:00</updated><title type='text'>Testing validation parameters using easyb in Grails</title><content type='html'>&lt;span class="Apple-style-span"   style="  ;font-family:arial;font-size:12px;"&gt;&lt;p&gt;If you want to test out domain class constraints, you can use easyb as &lt;br /&gt;follows: &lt;br /&gt;&lt;/p&gt;&lt;p&gt;My domain class is Subscription.groovy, and it has several &lt;br /&gt;parameters.  Only one parameter is required: subscriptionCode.  If you &lt;br /&gt;have any complex data types (such as my LmsTimeZone domain class) you &lt;br /&gt;need to provide those or the test fails.   When you validate, you can &lt;br /&gt;check the parameters that failed with the ensure method.  Here's an &lt;br /&gt;example: &lt;br /&gt;&lt;/p&gt;&lt;p&gt;scenario "Subscription cannot be created without a subscription code", &lt;br /&gt;{ &lt;br /&gt;        given "A new Subscription",{ &lt;br /&gt;                subscription = new Subscription() &lt;br /&gt;        } &lt;br /&gt;        when "required parameters are supplied except subscriptionCode", { &lt;br /&gt;                subscription.subscriptionCode = null &lt;br /&gt;                subscription.activationTimeZone = LmsTimeZone.get(1) &lt;br /&gt;                subscription.expirationTimeZone = LmsTimeZone.get(1) &lt;br /&gt;        } &lt;br /&gt;        then "the subscription validation shows subscriptionCode is not &lt;br /&gt;supplied", { &lt;br /&gt;                subscription.validate().shouldBe false &lt;br /&gt;                ensure(subscription.errors) { &lt;br /&gt;                        contains "subscriptionCode" &lt;br /&gt;                } &lt;br /&gt;                subscription.save(flush:true).shouldBe null &lt;br /&gt;        } &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div id="qhide_731" class="qt" style="display: block; "&gt;} &lt;br /&gt;&lt;br /&gt;&lt;/div&gt;I saved this as SubscriptionStory.groovy in my test/behavior package. &lt;br /&gt;Make sure you use the keyword "Story" or "Behavior" when making your &lt;br /&gt;test classes or easyb will not pick up your test. &lt;br /&gt;&lt;p&gt;Hope that helps someone out there, it took me a bit to figure it out! &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-5149994130579358457?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/5149994130579358457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/5149994130579358457'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2009/05/if-you-want-to-test-out-domain-class.html' title='Testing validation parameters using easyb in Grails'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-2835290757741226646</id><published>2009-01-02T19:24:00.000-08:00</published><updated>2009-11-07T17:23:18.561-08:00</updated><title type='text'>Grails Rich UI: Maintaining the tab on refresh</title><content type='html'>&lt;div&gt;Ahh, after hours of hacking, I finally got this to work! (and I do mean hacking)  It may not be the most elegant way of doing this, but it works.  I'll re-engineer it later if necessary.   I don't profess to be the worlds greatest JavaScripter, or Ajaxer, but here goes...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PROBLEM: &lt;/div&gt;&lt;div&gt;I use RichUI for my tabs in a Grails application.  The tabs look good, and it works well, except for one problem.  When you refresh the page, the tab reverts back to the first tab.  So, if you do cool stuff like adding in something with a modal or dialog, and you go back to your page, it reverts back to the first tab.  Sort of annoying and the customer complained.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;RESEARCH:&lt;/div&gt;&lt;div&gt;Eric Miraglia at ericmiraglia.com sent me this helpful url: &lt;a href="http://ericmiraglia.com/yui/demos/tabcookie.php"&gt;http://ericmiraglia.com/yui/demos/tabcookie.php&lt;/a&gt;&lt;/div&gt;&lt;div&gt;(Thanx!)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which was close to what I needed.  I also saw Tom Duerr's reply at the bottom of this page which was also very helpful:&lt;/div&gt;&lt;div&gt;&lt;a href="http://docs.codehaus.org/display/GRAILS/RichUI+Plugin"&gt;http://docs.codehaus.org/display/GRAILS/RichUI+Plugin&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, I couldn't get Tom's stuff to work out of the box.  The Ajax call just would not work for me.  So here's what I did to modify it a bit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;THEORY:&lt;/div&gt;&lt;div&gt;I wanted to store the tab index in a session, since most of my other temp stuff was stored in the session.  I didn't want to start down the cookie route in case people didn't want cookies on their machine.  So, I used Tom's mods to RichUI to allow for a tab index to be inserted into the Tab View, and I stored the tab info in the session.  Sounds easy, right?  Well, it took me most of the day to get it working well.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;IMPLEMENTATION:&lt;/div&gt;&lt;div&gt;First, make the mods to RichUI's TabViewRenderer.groovy just as Tom describes in the above link.  Next, update your instantiation of tab viewer in your gsp page from the standard:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;lt;richui:tabView id="tabView"&amp;gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;to this&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;lt; richui:tabView id="tabView" curTab="${curTab}" &lt;/div&gt;&lt;div&gt;event="processTab('type',${myObj?.id});"&amp;gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The curTab parameter is where you insert the current tab index, starting at 0 for the left most tab, 1 for the next tab to the right, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The event parameter holds a JavaScript method you want called whenever someone hits a tab.(i.e. an event occurrs)  You don't have to pass anything to this JavaScript method.  However, I pass in a "type" and an ID.  I do this because I don't want the same tab coming up whenever the user selects another object, or if I reuse this code on another page.  For instance, say some one wants to look at object 1, and they hit tab 3.  Now, if they browse around and find object 2, they want to see tab 0 to start off with, not tab 3.  So, I use the type, id, and tab number to make sure you are on the same page, viewing the same object.  If a user selects a different item from the list, they start at the 0 tab again.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The JavaScript processTab method looks like this: (added to the gsp where the tab view is)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;lt;script&amp;gt;&lt;/div&gt;&lt;div&gt;function processTab(type, id) {&lt;/div&gt;&lt;div&gt;var idx = tabView.get('activeIndex');&lt;/div&gt;&lt;div&gt;new Ajax.Request("/yourProject/yourController/currentTab?type=" + &lt;/div&gt;&lt;div&gt;type + "&amp;amp;id=" + id + "&amp;amp;currentTab=" + idx, { method:'get' });&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically, the tabView gives you the active index (the one someone just clicked on).  This is the value you want to pass to your controller method, along with the type of object and the id.  The controller will handle setting the values in the session.  (I couldn't figure out how to set the session in JavaScript, so I let the Grails controller do it via an asynchronous Ajax call.)  To get the parameters to the controller, I passed the parameters in the URL call.  The prototype manual indicated you can do this with 'parameter', which is probably the proper way to do this, but I couldn't figure it out right away (and my frustration with this grew exponentially by the minute), so I just went all brute force on it and passed the parameters in the URL myself.  Feel free to make it better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, it was time to go to the controller and create the "currentTab" method where I grabbed the values from the params object:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    def currentTab = {&lt;/div&gt;&lt;div&gt;        session.curTab = params.currentTab&lt;/div&gt;&lt;div&gt;        session.tabType = params.type&lt;/div&gt;&lt;div&gt;        session.tabId = new Long(params.id)&lt;/div&gt;&lt;div&gt;        return&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, back in the .gsp where the tab view is, I added this gem of logic:&lt;/div&gt;&lt;div&gt;    &lt;/div&gt;&lt;div&gt;&amp;lt;g:if test="${(session.curTab != 0) &amp;amp;&amp;amp; &lt;/div&gt;&lt;div&gt; (session.tabType == 'type') &amp;amp;&amp;amp; &lt;/div&gt;&lt;div&gt; (session.tabId == myObj?.id)}"&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;g:set var="curTab" value="${session.curTab}"/&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;/g:if&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;g:else&amp;gt;&lt;/div&gt;&lt;div&gt;    &amp;lt;g:set var="curTab" value="0"/&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;/g:else&amp;gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What this basically means is, set the curTab parameter to zero UNLESS the planets align and you actually viewing the same object, of the same type, with a tab index not already zero.  (the one and only true case where I actually want to save the tab index!).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After all that, it finally worked.  Hopefully someone out there will figure out an easier way, or just add all this into the next release of RichUI!  You can also do something similar with GrailsUI or even YUI if you want.  Eric's link above does it for you using YUI and cookies if you want to go that route.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, I just have to figure out how I can write a test to test this!  Of course, I know what a real Agile developer would say: I should have written the test first.  But, I'm just glad I got this bad boy working for now.  I need to eventually go live with this thing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-Keith&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PS.  I modified the plugin to allow for curTab to be set.  Also, I used richui 0.4 and grails 1.0.4 for this.  Using the latest richui 0.6 doesn't seem to work, so I'll have to do more research.  Anyway, modify the TabViewRenderer.groovy in the src directory of the plugin and change line 17 to look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica; font-size: medium; "&gt;builder.yieldUnescaped "    var tabView = new YAHOO.widget.TabView(\"${attrs.id}\", {activeIndex:\"${attrs.curTab}\"});\n"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Helvetica, serif;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Helvetica, serif;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;That is necessary for the plugin to tell YUI to set the activeIndex.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Helvetica, serif;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Helvetica, serif;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Thanks to Kevin Kruse for pointing this out!&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-2835290757741226646?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/2835290757741226646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/2835290757741226646'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2009/01/grails-rich-ui-maintaining-tab-on.html' title='Grails Rich UI: Maintaining the tab on refresh'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-4441581817015980316</id><published>2008-12-02T09:47:00.001-08:00</published><updated>2008-12-02T10:07:45.072-08:00</updated><title type='text'>Using the Filter Plugin for Grails</title><content type='html'>The filter plugin is a very useful tool if you want to be able to narrow down your lists in a convenient way.   For more info on the plugin check out &lt;a href="http://www.grails.org/Filter+plugin"&gt;http://www.grails.org/Filter+plugin&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once you install the plugin, also check out the example app.  Some of the things that were not so obvious when using Filter are as follows:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. Version 0.1 only works for the "list" action.  Make sure you only use this on the controller/list type of action.  Any other action, and it will not work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. Make sure you include prototype and scriptaculous in the header of your list.gsp.  This is important because the plugin will just sit there and do nothing without these libraries.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. Use a template called _list.gsp for your list table.  Filter currently expects this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4. Name your model data after your plugin with the "List" keyword added.  For example: if your controller is foobar, make sure your data model contains and is expecting a "foobarList" to iterate over for the list.  If you re-name this to something else, it won't work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5. Add a div tag where the id is "list"around your entire list in the template.  Filter expects this when rendering.  (you can see an example in the example app you downloaded)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6. It doesn't hurt to initialize max and offset in your controller. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;class foobar {&lt;/div&gt;&lt;div&gt;  def list = {&lt;/div&gt;&lt;div&gt;    if (!params.max) params.max = 10&lt;/div&gt;&lt;div&gt;    if (!params.offset) params.offset = 0 &lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7. Paginate requires "total" to be in the model.  Define total and return it in your controller.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One current limitation to the Filter plugin is this: If you want to use a narrowed result set (i.e. Foobar.findAllByStatus("Active")), and you set "total" in your controller using Foobar.countByStatus("Active"),  Filter only takes the count from the class when it finishes filtering.  That is, it does a clazz.count() which is basically a Foobar.count().  It also just takes the list from the parameters given (i.e. Foobar.list(params)).  What happens is, your count will be off in your pagination and result set after filtering.  You will see more data in your results after you  filter than the initial list.  You'll have to either modify the FilterController to fix this, or wait for a new release where this might be addressed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a great plugin with lots of potential.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;div&gt;-Keith &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-4441581817015980316?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/4441581817015980316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/4441581817015980316'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/12/using-filter-plugin-for-grails.html' title='Using the Filter Plugin for Grails'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-8403171680973636031</id><published>2008-07-31T09:47:00.000-07:00</published><updated>2008-07-31T10:07:52.580-07:00</updated><title type='text'>Creating a new Grails tag to convert military time to standard time</title><content type='html'>I have a situation where I need to store time as military time (i.e. 0900 is 9:00 AM), but I want to display it as standard time.  So, I created a new tag library in Grails to perform this for me.  I then simply use the new tag in my gsp page, and all is well.  Here's the code you would put in your taglib directory:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class MyTagLib {&lt;br /&gt;   def standardTime = {attrs, body -&gt;&lt;br /&gt;       out &lt;&lt; showStdTime(body())&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def showStdTime(militaryTime) {&lt;br /&gt;       def hours&lt;br /&gt;       def minutes&lt;br /&gt;       def ampm = "AM"&lt;br /&gt;       if (militaryTime.trim().size() != 4) {&lt;br /&gt;           return militaryTime&lt;br /&gt;       }&lt;br /&gt;       try {&lt;br /&gt;           hours = new Integer(militaryTime[0..1])&lt;br /&gt;           minutes = militaryTime[2..3]&lt;br /&gt;&lt;br /&gt;           if (hours &gt; 12) {&lt;br /&gt;               ampm = "PM"&lt;br /&gt;               hours -= 12&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           if (hours == 12) {&lt;br /&gt;               ampm = "PM"&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           if (hours == 0) {&lt;br /&gt;               hours = 12&lt;br /&gt;           }&lt;br /&gt;       } catch (Exception e) {&lt;br /&gt;           return "Format Exception: " + e.toString()&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       return hours + ":" + minutes + " " + ampm&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And here's the tag as it looks in my gsp page (substitute the lt for &lt;&gt;.  I couldn't get the formatting working right):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;g:standardtime&amp;gt;${myClass.closingTime}&amp;lt;/g:standardTime&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-8403171680973636031?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/8403171680973636031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/8403171680973636031'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/07/creating-new-grails-tag-to-convert.html' title='Creating a new Grails tag to convert military time to standard time'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-3806299225919031239</id><published>2008-03-26T11:33:00.000-07:00</published><updated>2008-03-26T11:35:22.357-07:00</updated><title type='text'>More on changing a button name when toggling show/hide</title><content type='html'>Here's a cool way of making the div area hidden first:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://you.gotfoo.org/using-scriptaculous-to-toggle-a-div/"&gt;http://you.gotfoo.org/using-scriptaculous-to-toggle-a-div/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-3806299225919031239?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/3806299225919031239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/3806299225919031239'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/03/cochran-software-changing-button-name.html' title='More on changing a button name when toggling show/hide'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-6171897715250805058</id><published>2008-03-26T09:45:00.000-07:00</published><updated>2008-03-26T09:52:16.109-07:00</updated><title type='text'>Dynamic messaging and i18n in Grails</title><content type='html'>When using &lt;a href="http://grails.org/"&gt;Grails &lt;/a&gt;for internationalization (i18n), you sometimes want to send some dynamic data to insert into the string.  For instance, you don't just want to say "User not found.", you want to say "Keith Cochran not found.".  So, to do that, you need to pass that information at runtime.  Here's how to do that.&lt;br /&gt;&lt;br /&gt;In your messages.properties file, add an {x} where you want your dynamic parameters to go.  Number them starting at 0.  For instance, define user.not.found in messages.properties like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;user.not.found={0} {1} not found&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, when you call up that particular string from a controller, pass in the variables you want to display at runtime:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;flash.message = message(code: "user.not.found",&lt;br /&gt;args: [user.firstname, user.lastname])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This makes your messaging back to the user much more informative.&lt;br /&gt;&lt;br /&gt;-Keith&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-6171897715250805058?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/6171897715250805058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/6171897715250805058'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/03/dynamic-messaging-and-i18n-in-grails.html' title='Dynamic messaging and i18n in Grails'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-8867736817500920184</id><published>2008-03-26T09:09:00.000-07:00</published><updated>2008-03-26T09:36:19.403-07:00</updated><title type='text'>Notes on Grails Internationalization (i18n)</title><content type='html'>When using &lt;a href="http://grails.org"&gt;Grails &lt;/a&gt;for web app development, it's desirable to place all text in messages.properties files.  When you do this, you can easily change the text to another language, and that makes &lt;a href="http://grails.org/Internationalization"&gt;internationalization &lt;/a&gt;easier.  You still have to deal with other issues such as date formats and currency, but at least the text is easy to modify that way. &lt;br /&gt;&lt;br /&gt;Once you have all your properties files created, you can make change languages by passing in the lang parameter and setting it to the language of your choice.  For instance, if you want to list out some values, you can call the "list" action and pass it the Spanish language as a parameter.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;&amp;lt;g:link action="list" params="[lang:'es']"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note: Once you pass this parameter to any page, your app will now be in that language until you change it.&lt;br /&gt;&lt;br /&gt;So, in order to facilitate this, you need to create the necessary files and reference the properties in your code.  For example, create a &lt;span style="font-weight: bold;"&gt;messages.properties&lt;/span&gt; file and add text such as "&lt;span style="font-style: italic;"&gt;Search&lt;/span&gt;" for your home page.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:100%;" &gt;&lt;span style="font-family: courier new;"&gt;home.search=Search&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, you can create a &lt;span style="font-weight: bold;"&gt;messages_es.properties&lt;/span&gt; that contains your Spanish translations:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-family: courier new;"&gt;home.search=Buscar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, once you have all the text defined in your messages.properties file(s), (one for each language you are translating to) all you then need to  do is reference that particular property in your code.  Grails picks that up and inserts the appropriate property for you.  Here are some tips on doing that in your code.&lt;br /&gt;&lt;br /&gt;In the GSP page, if you want to reference the file in just plain text, use the g:message tag:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;&amp;lt;g:message code="home.search" default="Search"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tells Grails to find the property "home.search" in the properties file, and insert that value here.  If it cannot find "home.search" in your properties file, it will insert whatever is in the default parameter.&lt;br /&gt;&lt;br /&gt;When using the sortableColumn GSP tag, use the "titleKey" parameter to set the property as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;&amp;lt;g:sortableColumn property="title" titleKey="certification.title"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To set the text of a button, you can pass in a variable from the controller.  I've used the flash scope to pass data back to the view, but you can use another object if you want to and return it.  First, grab the value from the flash scope in the GSP page as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;&amp;lt;input type="submit" value="${flash.search}"/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next, in the controller action, just set the flash.search parameter before you return:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;flash.search = message(code: 'home.search')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, the action in the controller will grab the message and throw it into the flash.search variable.  You simply read that variable in the GSP page and it's all good.  There's probably a better way of reading that parameter directly in the GSP page, and when I find it, I'll post an update.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-8867736817500920184?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/8867736817500920184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/8867736817500920184'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/03/notes-on-grails-internationalization.html' title='Notes on Grails Internationalization (i18n)'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3896461559970632672.post-9012361935890034896</id><published>2008-03-25T14:39:00.001-07:00</published><updated>2008-03-25T15:15:18.069-07:00</updated><title type='text'>Changing a button name when toggling show/hide</title><content type='html'>If you have a button that does a &lt;a href="http://script.aculo.us/"&gt;Scriptaculous&lt;/a&gt; &lt;a href="http://wiki.script.aculo.us/scriptaculous/show/Effect.toggle"&gt;toggle&lt;/a&gt;, you can have the text of the button changes from "Show" to "Hide" by updating the text property of the button using JavaScript and AJAX.  Here's how you do it:&lt;br /&gt;&lt;br /&gt;First, define the button and the area in which you want to show/hide.  In this case, I have a change history that can get quite large, so I want to be able to toggle it on and off, with some scriptactulous pizazz.  So, I first define the button as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Change History:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;form action="javascript:void%200" method="get"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;button type="button" id="switchoff" class="togglebutton"&lt;br /&gt;name="switchoff"&amp;gt;Hide&amp;lt;/button&amp;gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Next, define then area to show/hide using a div tag with an id.  I'll use the id of "change_history" in this case.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&amp;lt;div id="change_history"&amp;gt;&lt;br /&gt;&amp;lt;table&amp;gt;&amp;lt;!-- this is just a table with my&lt;br /&gt;change history in it --&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, now that I have my elements named and defined, it's time to set up some JavaScript to handle the toggle.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;window.onload = function() {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;    /**&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;     * Toggle change history.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;     */&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;    if ($("change_history") &amp;amp;&amp;amp; $("switchoff")) {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;        $("switchoff").onclick = function() {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            &lt;span style="color: rgb(51, 204, 0);"&gt;// Effect.toggle(element,&lt;br /&gt;          //   ['appear' | 'slide' | 'blind'], [options] );&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            Effect.toggle($("change_history"), 'appear');&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            var toggleButton =&lt;br /&gt;            document.getElementById('switchoff');&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            if (toggleButton.textContent == "Show") {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;              toggleButton.textContent = "Hide";&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            } else if (toggleButton.textContent == "Hide") {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;                toggleButton.textContent = "Show";&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            } else {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;                toggleButton.textContent = "Show";&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;            }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;        }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;    }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Put this JavaScript at the top of your web page in the  section or, preferably, in another JavaScript file and reference it from your web page.  I usually do the later.  Basically, this JavaScript looks for elements named "change_history" and "switchoff", and if they are available, then go ahead and perform the function.&lt;br /&gt;&lt;br /&gt;It next defines the onclick() method for switchoff so that, when clicked, use Scriptaculous to toggle the change_history (i.e. if it's shown, then hide it.  If it's hidden, show it).  This is all basic Scriptactulous, so nothing new here.  However, now the JavaScript tries to determine if the text of the button is currently "Show" or "Hide".  It will change it to the opposite of what it is now.  The last case is for those who didn't originally use "Show" or "Hide" for the button name.  It will basically change it go "Show" the first time you hide what you want to hide.&lt;br /&gt;&lt;br /&gt;That's about it.  Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3896461559970632672-9012361935890034896?l=cochransoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/9012361935890034896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3896461559970632672/posts/default/9012361935890034896'/><link rel='alternate' type='text/html' href='http://cochransoftware.blogspot.com/2008/03/changing-button-name-when-toggling.html' title='Changing a button name when toggling show/hide'/><author><name>Keith Cochran</name><uri>http://www.blogger.com/profile/12946865691478456663</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
