Index: /trunk/grails-app/services/AssetTreeService.groovy
===================================================================
--- /trunk/grails-app/services/AssetTreeService.groovy	(revision 321)
+++ /trunk/grails-app/services/AssetTreeService.groovy	(revision 322)
@@ -3,5 +3,5 @@
     boolean transactional = false
 
-    def js = new JavascriptService()
+    def js = new JsUtilService()
 
     def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
@@ -84,5 +84,5 @@
 
                 div(class: paneCloseHtmlClass()) {
-                    a( href: js.hrefToggle(paneHtmlId()) ) {
+                    a( href: js.toggle(paneHtmlId()) ) {
                         img(src: closeImg())
                     }
@@ -106,5 +106,5 @@
                 div( class: 'buttons') {
                     span(class: 'button') {
-                        input( type: 'button', value: g.message(code: 'default.close.text'), onclick: js.onclickToggle(paneHtmlId()) )
+                        input( type: 'button', value: g.message(code: 'default.close.text'), onclick: js.toggle(paneHtmlId(), "onclick") )
                     }
                 } // button div
@@ -132,5 +132,5 @@
                                 li() {
                                     if(site.sections) {
-                                        a(href: hrefToggleBranch(nextDivId()) ) {
+                                        a(href: toggleBranch(nextDivId()) ) {
                                             img( src: branchImg(divId), id: divId+'img' )
                                         }
@@ -152,5 +152,5 @@
                                                 li() {
                                                     if(section.assets) {
-                                                        a( href: hrefToggleBranch(nextDivId()) ) {
+                                                        a( href: toggleBranch(nextDivId()) ) {
                                                             img(src: branchImg(divId), id: divId+'img' )
                                                         }
@@ -173,5 +173,5 @@
                                                                 li() {
                                                                     if(asset.assetSubItems) {
-                                                                        a( href: hrefToggleBranch(nextDivId()) ) {
+                                                                        a( href: toggleBranch(nextDivId()) ) {
                                                                             img(src: branchImg(divId), id: divId+'img' )
                                                                         }
@@ -197,5 +197,5 @@
                                                                                 li() {
                                                                                     if(assetSubItemL1.subItems) {
-                                                                                        a( href: hrefToggleBranch(nextDivId()) ) {
+                                                                                        a( href: toggleBranch(nextDivId()) ) {
                                                                                             img(src: branchImg(divId), id: divId+'img' )
                                                                                         }
@@ -218,5 +218,5 @@
                                                                                                 li() {
                                                                                                     if(assetSubItemL2.subItems) {
-                                                                                                        a( href: hrefToggleBranch(nextDivId()) ) {
+                                                                                                        a( href: toggleBranch(nextDivId()) ) {
                                                                                                             img( src: branchImg(divId), id: divId+'img' )
                                                                                                         }
@@ -239,5 +239,5 @@
                                                                                                                 li() {
                                                                                                                     if(assetSubItemL3.subItems) {
-                                                                                                                        a( href: hrefToggleBranch(nextDivId()) ) {
+                                                                                                                        a( href: toggleBranch(nextDivId()) ) {
                                                                                                                             img( src: branchImg(divId), id: divId+'img' )
                                                                                                                         }
@@ -260,5 +260,5 @@
                                                                                                                                 li() {
             //                                                                                                                         if(assetSubItemL4.subItems) {
-            //                                                                                                                             a( href: hrefToggleBranch(nextDivId()) ) {
+            //                                                                                                                             a( href: toggleBranch(nextDivId()) ) {
             //                                                                                                                                 img( src: branchImg(divId), id: divId+'img' )
             //                                                                                                                             }
@@ -365,6 +365,6 @@
     }
 
-    def hrefToggleBranch(divId) {
-       'javascript: toggleBranch(\"' + divId + '\", \"' + divId + 'img' +'\", \"' + bulletTreeMinusImg() +'\", \"' + bulletTreePlusImg() + '\");'
+    def toggleBranch(divId) {
+        js.toggleWithImg(divId, divId + 'img', bulletTreeMinusImg(), bulletTreePlusImg())
     }
 
Index: unk/grails-app/services/JavascriptService.groovy
===================================================================
--- /trunk/grails-app/services/JavascriptService.groovy	(revision 321)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/**
-* Provides some javascript utility methods.
-* To use include the following in the gsp head:
-* <!--
-* <g:javascript src="util.js" />
-* -->
-* @todo: util.js could be placed a taglib resources closure.
-*/
-class JavascriptService {
-
-    boolean transactional = false
-
-    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
-
-    /**
-    * Toggle the visibility of an html element.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an onclick action.
-    */
-    def onclickToggle(id) {
-        'return toggleUtil(\"' + id + '\");'
-    }
-
-    /**
-    * Toggle the visibility of an html element.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an anchor href.
-    */
-    def hrefToggle(id) {
-        'javascript: toggleUtil(\"' + id + '\");'
-    }
-
-    /**
-    * Show an html element by slowly increasing the visibility.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an onclick action.
-    */
-    def onclickShow(id) {
-        'return showUtil(\"' + id + '\");'
-    }
-
-    /**
-    * Show an html element by slowly increasing the visibility.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an anchor href.
-    */
-    def hrefShow(id) {
-        'javascript: showUtil(\"' + id + '\");'
-    }
-
-    /**
-    * Hide an html element by slowly decreasing the visibility.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an onclick action.
-    */
-    def onclickHide(id) {
-        'return hideUtil(\"' + id + '\");'
-    }
-
-    /**
-    * Hide an html element by slowly decreasing the visibility.
-    * @param id The html id of the element.
-    * @returns A javascript string that can be assigned to an anchor href.
-    */
-    def hrefHide(id) {
-        'javascript: hideUtil(\"' + id + '\");'
-    }
-
-} // end class
Index: /trunk/grails-app/services/JsUtilService.groovy
===================================================================
--- /trunk/grails-app/services/JsUtilService.groovy	(revision 322)
+++ /trunk/grails-app/services/JsUtilService.groovy	(revision 322)
@@ -0,0 +1,72 @@
+/**
+* Provides some javascript utility methods.
+* For use with JsUtilTagLib.
+*/
+class JsUtilService {
+
+    boolean transactional = false
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    /**
+    * Toggle the visibility of an html element.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def toggle(id, type="href") {
+        def s = 'toggleUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+    /**
+    * Toggle the visibility of an html element and update an image.
+    * @param toggleId The html id of the element to toggle.
+    * @param imageid The html id of the image to update.
+    * @param openImgUrl The url to apply as the image src when toggled element is visible.
+    * @param closedImgUrl The url to apply as the image src when toggled element is hidden.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def toggleWithImg(toggleId, imageid, openImgUrl, closedImgUrl, type="href") {
+
+        def s = 'toggleWithImgUtil(\"' + toggleId +'\", \"' + imageid +'\", \"' + openImgUrl +'\", \"' + closedImgUrl +'\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+
+    }
+
+    /**
+    * Show an html element by slowly increasing the visibility.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def show(id) {
+        def s = 'showUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+    /**
+    * Hide an html element by slowly decreasing the visibility.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def hide(id) {
+        def s = 'hideUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+} // end class
Index: /trunk/grails-app/taglib/AssetTreeTagLib.groovy
===================================================================
--- /trunk/grails-app/taglib/AssetTreeTagLib.groovy	(revision 321)
+++ /trunk/grails-app/taglib/AssetTreeTagLib.groovy	(revision 322)
@@ -6,5 +6,5 @@
     static namespace = 'gnuMims'
 
-    def js = new JavascriptService()
+    def js = new JsUtilService()
     def ts = new AssetTreeService()
 
@@ -37,5 +37,5 @@
         mkp.div(class: ts.paneHtmlClass(), id: ts.paneHtmlId(), style: 'display:none;') {
             div(class: ts.paneCloseHtmlClass()) {
-                a( href: js.hrefToggle(ts.paneHtmlId()) ) {
+                a( href: js.toggle(ts.paneHtmlId()) ) {
                     img(src: ts.closeImg())
                 }
Index: /trunk/grails-app/taglib/JsUtilTagLib.groovy
===================================================================
--- /trunk/grails-app/taglib/JsUtilTagLib.groovy	(revision 322)
+++ /trunk/grails-app/taglib/JsUtilTagLib.groovy	(revision 322)
@@ -0,0 +1,39 @@
+
+/**
+* JsUtil tags.
+* Javascript Utility tags.
+*/
+class JsUtilTagLib {
+    static namespace = 'jsUtil'
+
+    def js = new JsUtilService()
+
+    /**
+    * Resources.
+     * To be included in the page head tag.
+    */
+    def resources = { attrs ->
+        out << g.javascript(src: "jsUtil.js")
+    }
+
+    /**
+    * Toggle the visibility of an html element and update an image.
+    * @param toggleId The html id of the element to toggle.
+    * @param imageId The html id to apply to the image.
+    * @param openImgUrl The url to apply as the image src when toggled element is visible.
+    * @param closedImgUrl The url to apply as the image src when toggled element is hidden.
+    * @param text The text, if any, to display.
+    */
+    def toggleControl = { attrs ->
+        def mkp = new groovy.xml.MarkupBuilder(out) //this line will be unnecessary in versions of Grails after version 1.2
+
+        mkp.div() {
+            a( href: js.toggleWithImg(attrs.toggleId, attrs.imageId, attrs.openImgUrl, attrs.closedImgUrl) ) {
+                yieldUnescaped(attrs.text)
+                img(id: attrs.imageId, src: attrs.closedImgUrl, alt: "Show")
+            }
+        } // mkp
+
+    } // hideShowControl
+
+} // end class
Index: /trunk/grails-app/views/layouts/main.gsp
===================================================================
--- /trunk/grails-app/views/layouts/main.gsp	(revision 321)
+++ /trunk/grails-app/views/layouts/main.gsp	(revision 322)
@@ -11,5 +11,5 @@
         <g:javascript library="prototype/effects" />
         <g:javascript src="overlayPane.js" />
-        <g:javascript src="util.js" />
+        <jsUtil:resources />
         <gnuMims:resources />
     </head>
Index: /trunk/web-app/js/assetTree.js
===================================================================
--- /trunk/web-app/js/assetTree.js	(revision 321)
+++ /trunk/web-app/js/assetTree.js	(revision 322)
@@ -4,9 +4,8 @@
     Effect.Appear(paneDivId,{duration:0.4});
 
-    // Pulsing loadingImg blocks the default grails animated gif till complete.
-    // After which the default will show as normal.
-    new Effect.Pulsate($(loadingImg), { pulses: 200, duration: 133 });
+    // Disabled since pulsing effect blocks other javascript till complete.
+    // The effect may be stopped with e.cancel() but we will use the default Grails spinner for now.
+    // def e = new Effect.Pulsate($(loadingImg), { pulses: 200, duration: 133 });
 
-    // The updater is only called once per page refresh.
     new Ajax.Updater({ success: paneDivId }, url, {asynchronous:true,evalScripts:true});
 }
@@ -34,15 +33,2 @@
     new Ajax.Request(saveUrl, {parameters: params, asynchronous: false});
 }
-
-function toggleBranch(divId, imageId, openImgUrl, closedImgUrl) {
-
-    $(divId).toggle();
-
-    if( $(divId).visible() ) {
-        $(imageId).src= openImgUrl;
-    }
-    else {
-        $(imageId).src= closedImgUrl;
-    }
-
-}
Index: /trunk/web-app/js/jsUtil.js
===================================================================
--- /trunk/web-app/js/jsUtil.js	(revision 322)
+++ /trunk/web-app/js/jsUtil.js	(revision 322)
@@ -0,0 +1,24 @@
+
+function toggleUtil(id) {
+    $(id).toggle();
+}
+
+function toggleWithImgUtil(id, imageId, openImgUrl, closedImgUrl) {
+
+    $(id).toggle();
+
+    if( $(id).visible() ) {
+        $(imageId).src= openImgUrl;
+    }
+    else {
+        $(imageId).src= closedImgUrl;
+    }
+}
+
+function showUtil(id) {
+    Effect.Appear(id,{duration:0.4,queue:'end'});
+}
+
+function hideUtil(id) {
+    Effect.Fade(id,{duration:0.4,queue:'end'});
+}
Index: unk/web-app/js/util.js
===================================================================
--- /trunk/web-app/js/util.js	(revision 321)
+++ 	(revision )
@@ -1,12 +1,0 @@
-
-function toggleUtil(id) {
-    $(id).toggle();
-}
-
-function showUtil(id) {
-    Effect.Appear(id,{duration:0.4,queue:'end'});
-}
-
-function hideUtil(id) {
-    Effect.Fade(id,{duration:0.4,queue:'end'});
-}
