You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2011/05/02 00:46:49 UTC

svn commit: r1098430 [3/4] - in /sling/trunk/samples: ./ accessmanager-ui/ accessmanager-ui/.settings/ accessmanager-ui/src/ accessmanager-ui/src/main/ accessmanager-ui/src/main/java/ accessmanager-ui/src/main/resources/ accessmanager-ui/src/main/resou...

Added: sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.js
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.js?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.js (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.js Sun May  1 22:46:46 2011
@@ -0,0 +1,1157 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Holds some common functions used by other user management objects 
+ */
+UserManager = {
+    /**
+     * Holds the servlet context path of the web application
+     */
+    contextPath: "",
+
+    /**
+     * Format a string by replacing tokens with the passed in arguments.
+     * 
+     * @param {String} msg The message pattern.  Use {n} for replacable arguments where n is the arg index.
+     * @param {Array} args array of arguments to apply to the message pattern
+     */
+    formatMsg: function(msg, args) {
+        var regex = /{(\d+)}/g;
+        return msg.replace(regex, function() {
+            var index = parseInt(arguments[1]);
+            return args[index];
+        });
+    },
+    
+    /**
+     * Resource strings for usermgmt that can be localized for other languages
+     */
+    messages: {
+        "error.dlg.title": "Error",
+        "confirm.yes": "Yes",
+        "confirm.no": "No",
+        "button.add": "Add",
+        
+        "searching.progress.msg": "Searching, please wait...",
+        
+        "tooltip.removeProperty": "Remove Property",
+        "tooltip.removeMember": "Remove Member",
+        
+        "group.updated.msg": "Updated the group",
+        "user.updated.msg": "Updated the user",
+        "user.pwd.updated.msg": "Updated the password",
+        
+        "group.created.msg": "Created the group",
+        "user.created.msg": "Created the user"
+    }    
+}
+
+/**
+ * For the navigation links in the left side of the page.
+ */
+UserManager.SideBar = {
+    /**
+     * Initialize SideBar elements
+     */
+    init: function() {
+        var i, navLinks, url, hash, nav;
+        
+        // highlight the link for the current page
+        navLinks = $("ul#sidebar-nav li a");
+        url = location.href;
+        hash = location.hash;
+        if (hash != null && hash.length > 0) {
+            url = url.substring(0, url.length - hash.length);
+        }
+        for (i=0; i < navLinks.length; i++) {
+            nav = navLinks[i];
+            if (url == nav.href) {
+                $(nav.parentNode).addClass("ui-corner-all ui-state-highlight");
+            }
+        }
+    }
+}
+
+/**
+ * For showing an error dialog when something goes wrong.
+ */
+UserManager.ErrorDlg = {
+    /**
+     * Show a modal dialog with the supplied content.
+     * @param {String} title The title text of the dialog
+     * @param {String} msg The html markup of the dialog body
+     */
+    showError: function(title, msg) {
+        // add an error_dialog div to the page if it doesn't already exist
+        if ($('#error_dialog').length == 0) {
+            $('body').append('<div id="error_dialog" style="display:none;"></div>');
+        }
+        //fill in the dialog body
+        $('#error_dialog').html( msg );
+        $('#error_dialog').dialog({
+            title: title,
+            bgiframe: true, 
+            autoOpen: false, 
+            width: 400,
+            maxHeight: 500,
+            modal: true
+        });
+        //show the modal dialog
+        $('#error_dialog').dialog('open');
+    },
+    
+    /**
+     * Handles an error from an AJAX call by showing the error information
+     * in a modal dialog.
+     */
+    errorHandler: function( xmlHttpRequest, textStatus, errorThrown ) {
+        var title, obj;
+        try {
+            title = UserManager.messages["error.dlg.title"];
+            //see if the response is a JSON resoponse with an error field
+            obj = $.parseJSON(xmlHttpRequest.responseText);
+            if (obj.error) {
+                //found error field, so show the error message
+                UserManager.ErrorDlg.showError(title, obj.error.message);                        
+            } else {
+                //no error field, so show the whole response text
+                UserManager.ErrorDlg.showError(title, xmlHttpRequest.responseText);                        
+            }
+        } catch (e) {
+            //Not JSON? Show the whole response text.
+            UserManager.ErrorDlg.showError(title, xmlHttpRequest.responseText);                        
+        }                        
+    }
+};
+
+/**
+ * For pages the that search for Users or Groups.
+ */
+UserManager.Authorizables = {
+    /**
+     * Holds the id of the searching progress function (if any).
+     */
+    progressFnId: null,
+    
+    /**
+     * Initializes the elements for the User/Group search page
+     */
+    init: function() {
+        //apply styles to the quick-nav radio buttons
+        $('#find-authorizables-quick-nav').buttonset().show();
+
+        //apply styles and handlers to the search result table 
+        UserManager.Authorizables.applyResultStylesAndHandlers();
+        
+        /**
+         * Attach event handlers to the quick-hav radio buttons
+         */
+        $('#find-authorizables-quick-nav input[type = "radio"]').change( function (e) {
+            //reset the paging to the first page
+            $('#searchOffset').val(0);
+
+            //do the search
+            UserManager.Authorizables.runSearchFn();
+            return false;
+        });
+    
+        //apply jquery-ui styles to the search button
+        $('button#findAuthorizablesBtn').button();
+    
+        //attach event handler to the search button
+        $('button#findAuthorizablesBtn').click( function(e) {
+            if ($('#findAuthorizablesQuery').val() == '') {
+                //empty query == 'All'
+                $('#radioAll').attr('checked', true);
+                $('#radioAll').button('refresh');
+            } else {
+                //uncheck all the quick-nav radio buttons
+                $('#radioNone').attr('checked', true);
+                $('#radioNone').button('refresh');
+            }
+
+            //reset the paging to the first page
+            $('#searchOffset').val(0);
+            
+            //do the search
+            UserManager.Authorizables.runSearchFn();
+            return false;
+        });
+
+        /**
+         * Listen for changes to the location hash.  This is to
+         * make the browser history work (back button).
+         */
+        $(window).bind('hashchange', UserManager.Authorizables.runSearchFromHashFn);
+        
+        //trigger the search now in case we got here from the back button
+        $(window).trigger("hashchange");
+    },
+    
+    /**
+     * Displays a 'Loading...' progress animation if the search is taking
+     * a while to return.
+     */
+    progressFn: function() {
+        //inject a progress block
+        $('#authorizables-results-body')
+            .after('<div id="authorizables-results-progress" style="text-align:center"><img src="' + UserManager.contextPath + '/css/usermgmt/images/ajax-loader.gif" alt="' + UserManager.messages["searching.progress.msg"] +  '"/></div>');
+
+        //done with this.
+        UserManager.Authorizables.progressFnId = null;
+    },
+    
+    /**
+     * Removes the progress animation if it is present.
+     */
+    clearProgressFn: function() {
+        if (UserManager.Authorizables.progressFnId != null) { 
+            //stop the progress animation if it hasn't started yet.
+            clearTimeout(UserManager.Authorizables.progressFnId); 
+            UserManager.Authorizables.progressFnId = null;
+        }
+        //remove the old progress element from the page (if there)
+        $('#authorizables-results-progress').remove();
+    },
+
+    /**
+     * Executes the search, showing results starting at the
+     * specified offset
+     * @param {Number} offset the index of the first row to render
+     */
+    runSearchFn: function(offset) {
+        var form, formData;
+        
+        //update the offset field in the form
+        $('#searchOffset').val(offset == undefined ? "0" : offset);
+
+        form = $("#find-authorizables-form");
+        //serialize the form data to set as the location hash
+        formData = form.serialize();
+        
+        //changing the location hash triggers the ajax search call
+        // using the location hash here to make the browser back button work.
+        window.location.hash = formData;
+    },
+
+    /**
+     * Parse the location hash and extract the name/value pairs
+     */
+    parseHashParams: function() {
+        var hashParams = {},
+            e,
+            a = /\+/g,  // Regex for replacing addition symbol with a space
+            r = /([^&;=]+)=?([^&;]*)/g,
+            d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
+            q = window.location.hash.substring(1);
+
+        while (e = r.exec(q))
+           hashParams[d(e[1])] = d(e[2]);
+
+        return hashParams;
+    },
+    
+    /**
+     * Executes the search when a change to the location hash has
+     * been detected.
+     */
+    runSearchFromHashFn: function() {
+        var form, action, hashParams;
+
+        form = $("#find-authorizables-form");
+        action = form.attr('action');
+        //change the target sling selector to the searchresult fragment
+        action = action.substring(0, action.length - 4) + "searchresult.html";
+
+        //get the map of parameters in the hash string
+        hashParams = UserManager.Authorizables.parseHashParams()
+        
+        //fill the query text into the search input
+        $("#findAuthorizablesQuery").val(hashParams.q == undefined ? "" : hashParams.q);
+        //select the correct quick-nav radio button
+        $('#find-authorizables-quick-nav input[value="' + (hashParams.sp == undefined ? "" : hashParams.sp) + '"]')
+            .attr("checked", true)
+            .button('refresh');
+        //fill in the offset value
+        $('#searchOffset').val(hashParams.o == undefined ? "0" : hashParams.o);
+
+        if (hashParams.q == undefined && hashParams.sp == undefined) {
+            //the hashCode doesn't have a query, so don't to a search 
+            if ($("#search-result-ready-to-search").length == 0) {
+                // not on the ready-to-search page so we need to refresh the
+                // result panel to get the right UI.
+                $.ajax({
+                    url: action,
+                    type: 'get',
+                    success: UserManager.Authorizables.searchDoneFn,
+                    error: UserManager.ErrorDlg.errorHandler
+                });
+            }
+            return;
+        }
+        
+        //the hashCode has a query, so proceed.. 
+
+        //hide the old results table
+        $('#authorizables-results-body').hide();
+
+        //show a progress animation if the search takes longer than 200ms to return
+        UserManager.Authorizables.clearProgressFn();
+        UserManager.Authorizables.progressFnId = setTimeout(UserManager.Authorizables.progressFn, 200);
+
+        //do the search request.
+        $.ajax({
+            url: action,
+            type: 'get',
+            data: form.serialize(),
+            cache: false,
+            success: UserManager.Authorizables.searchDoneFn,
+            error: function(xmlHttpRequest, textStatus, errorThrown) {
+                //clear the progress animation if it is there.
+                UserManager.Authorizables.clearProgressFn();
+                
+                //delegate the rest to the generic error handler
+                UserManager.ErrorDlg.errorHandler(xmlHttpRequest, textStatus, errorThrown);
+            }
+        });
+    },
+
+    /**
+     * Callback function for a successful search request
+     */
+    searchDoneFn: function( data, textStatus, xmlHttpRequest ) {
+        //clear the progress animation if it is there.
+        UserManager.Authorizables.clearProgressFn();
+        
+        //inject the results table into the page
+        $('#authorizables-results-body').replaceWith(data);
+
+        //apply extra styles and event handlers to the results table
+        UserManager.Authorizables.applyResultStylesAndHandlers();
+    },
+
+    /**
+     * Apply styles and event handlers to the result table rows
+     */
+    applyResultStylesAndHandlers: function( data, textStatus, xmlHttpRequest ) {
+        //highlight the table row onHover
+        $("#search-result-body tr")
+            .mouseover(function(){
+                $(this).addClass("ui-state-highlight");
+            })
+            .mouseout(function(){
+                $(this).removeClass("ui-state-highlight");
+            })
+            .click(function(){
+                var href = $(this).find("td a")[0].href;
+                window.location = href;
+                return false;
+            });
+        
+        //attach event handlers to the paging buttons
+        $("#first_page").button()
+            .click(function() {
+                UserManager.Authorizables.runSearchFn(0);
+                return false;
+            });            
+        $("#prev_page").button()
+            .click(function() {
+                UserManager.Authorizables.runSearchFn($("#prev_page").val());
+                return false;
+            });
+        $("#next_page").button()
+            .click(function() {
+                UserManager.Authorizables.runSearchFn($("#next_page").val());
+                return false;
+            });
+    }
+};
+
+
+/**
+ * Holds some common functions for Group related pages 
+ */
+UserManager.Group = {
+        
+};
+
+/**
+ * For the Group create page.
+ */
+UserManager.Group.Create = {
+    /**
+     * Initializes the elements for the create Group page
+     */
+    init: function() {
+        //apply jquery-ui styles to create button
+        $('button#createGroupBtn').button();
+
+        // validate form
+        /*var validator = */$("#create-group-form").validate({
+            rules: {
+                ":name": "required"
+            }/*,
+            messages: {
+            }*/
+        });
+
+        //apply event handler to the create button
+        $('button#createGroupBtn').click( function(e) {
+            var form, actionUrl, formData;
+            
+            form = $("#create-group-form");
+            
+            //client side validation
+            if (!form.valid()) {
+                return false;
+            }
+            
+            actionUrl = form.attr('action');
+
+            //switch to a json response
+            actionUrl = actionUrl.substring(0, actionUrl.length - 4) + "json";
+
+            //turn off redirect in this context
+            $('#redirect').attr('disabled', true);
+            formData = form.serialize();
+            $('#redirect').removeAttr('disabled');
+
+            //hide the info msg from a previous action
+            $("#create-group-body div.info-msg-block").hide();
+            
+            //submit the create request
+            $.ajax({
+                url: actionUrl,
+                type: 'POST',
+                data: formData,
+                success: function( data, textStatus, xmlHttpRequest ) {
+                    //clear the inputs
+                    $("#create-group-form input[type='text']").val('');
+
+                    //inject a success message
+                    $("#create-group-body span.info-msg-text").html(UserManager.messages["group.created.msg"]);
+                    $("#create-group-body div.info-msg-block").show();
+                },
+                error: UserManager.ErrorDlg.errorHandler
+            });
+            
+            return false;
+        });
+    }
+};
+
+/**
+ * For the Group update page.
+ */
+UserManager.Group.Update = {
+    /**
+     * Initializes the elements for the create Group page
+     */
+    init: function() {
+        //apply jquery-ui styles to the update button
+        $('button#updateGroupBtn').button();
+
+        // validate form
+        /*var validator = */$("#update-group-form").validate({
+            rules: {
+            }/*,
+            messages: {
+            }*/
+        });
+        
+        //hover states on the remove member icons
+        $('.remove-member').hover(
+            function() { $(this).addClass('ui-state-hover'); }, 
+            function() { $(this).removeClass('ui-state-hover'); }
+        ).click(
+            function(e) {
+                //mark the member for deletion when the update is saved
+                var memberItem = $(e.currentTarget.parentNode);
+                memberItem.hide('slow', function() {
+                    if ($('ol#declaredMembers li:visible').length == 0) {
+                        $("#declaredMembers__empty").show();
+                    }
+                });
+                memberItem.find('input').attr("name", ":member@Delete");
+                
+                return false;
+            }
+        );
+
+        //hover states on the remove property icons
+        $('.remove-property').hover(
+            function() { $(this).addClass('ui-state-hover'); }, 
+            function() { $(this).removeClass('ui-state-hover'); }
+        ).click(
+            function(e) {
+                var memberItem, input, key;
+                
+                //mark the property for deletion when the update is saved
+                memberItem = $(e.currentTarget.parentNode);
+                memberItem.hide('slow');
+                input = memberItem.find('input');
+                key = input.attr("name");
+                input.attr("name", key + "@Delete");
+                return false;
+            }
+        );
+        
+        //attach event handler to the update button
+        $('button#updateGroupBtn').click( function(e) {
+            var form, actionUrl, formData;
+            
+            form = $("#update-group-form");
+
+            //client side validation
+            if (!form.valid()) {
+                return false;
+            }
+            
+            actionUrl = form.attr('action');
+
+            //switch to a json response
+            actionUrl = actionUrl.substring(0, actionUrl.length - 4) + "json";
+
+            //turn off redirect in this context
+            $('#redirect').attr('disabled', true);
+            formData = form.serialize();
+            $('#redirect').removeAttr('disabled');
+
+            //hide the info msg from a previous action
+            $("#update-group-body div.info-msg-block").hide();
+            
+            //submit the update request
+            $.ajax({
+                url: actionUrl,
+                type: 'POST',
+                data: formData,
+                success: function( data, textStatus, xmlHttpRequest ) {
+                    $("#content").load(UserManager.contextPath + data.path + ".update_body.html", function() {
+                        $("#update-group-body span.info-msg-text").html(UserManager.messages["group.updated.msg"]);
+                        $("#update-group-body div.info-msg-block").show();
+                    });
+                    
+                    setTimeout(function() {
+                        //re-init since we just replaced the body
+                        UserManager.Group.Update.init();
+
+                        //make visible any elements that require scripting to be enabled 
+                        $(".noscript-hide").removeClass("noscript-hide");
+                    }, 100);
+                },
+                error: UserManager.ErrorDlg.errorHandler
+            });
+            return false;
+        });
+
+        
+        //attach a confirmation dialog to the 'Remove' link
+        $('a#removeGroupLink').click( function(e) {
+            //initialize the confirmation dialog
+            $("#remove-group-dialog").dialog({
+                autoOpen: false,
+                height: 'auto',
+                width: 350,
+                modal: true,
+                resizable: false,
+                buttons: [
+                    {
+                        text: UserManager.messages["confirm.yes"],
+                        click: function() {
+                            $("#remove-group-form").submit();
+                        } 
+                    },
+                    {
+                        text: UserManager.messages["confirm.no"],
+                        click: function() {
+                            $("#remove-group-dialog").dialog("close");
+                        }
+                    }
+                ]
+            });
+
+            //show the dialog
+            $('#remove-group-dialog').dialog('open');
+            return false;
+        });
+
+        //attach a prompt dialog to the 'Add Property' link
+        $('a#add_property').click( function(e) {
+            //initialize the dialog
+            $("#add-property-dialog").dialog({
+                autoOpen: false,
+                height: 'auto',
+                width: 350,
+                modal: true,
+                resizable: false,
+                buttons: [
+                    {
+                        text: UserManager.messages["button.add"],
+                        click: function() {
+                            var form, name, label, newItem;
+                            
+                            form = $("#add-property-form");
+                            //client side validation
+                            if (!form.valid()) {
+                                return false;
+                            }
+                        
+                            //get new property name
+                            name=$("#newPropName").val();
+                            label = name;
+                            
+                            //inject property line for the new property
+                            $("#updateSubmitBtns").before('<div class="prop-line ui-helper-clearfix"><label for="' + name + '">' + label + ':</label> <input id="' + name + '" type="text" name="' + name + '" /> <a href="#" class="remove-property" title="' + UserManager.messages["tooltip.removeProperty"] + '"><span class="ui-icon ui-icon-circle-close"></span></a></div>');
+                            
+                            newItem = $("#updateSubmitBtns").prev();
+                            
+                            //add hover states on the remove property icons
+                            newItem.find('a.remove-property').hover(
+                                function() { $(this).addClass('ui-state-hover'); }, 
+                                function() { $(this).removeClass('ui-state-hover'); }
+                            ).click(
+                                function(e) {
+                                    var propItem = $(e.currentTarget.parentNode);
+                                    //haven't saved yet on server, so just remove this element from the page.
+                                    propItem.hide('slow', function() {
+                                        propItem.remove();
+                                    });
+                                    return false;
+                                }
+                            );
+                            
+                            //close the dialog
+                            $("#add-property-dialog").dialog( "close" );
+
+                            //give focus to the new property line
+                            newItem.find('input').focus();
+                        } 
+                    }
+                ]
+            });
+            
+            //clear old value from the dialog (if there)
+            $("#newPropName").val('');
+            
+            //open the dialog
+            $('#add-property-dialog').dialog('open');
+            return false;
+        });
+
+        //forward the form submit event to the button handler to handle 'Enter' key in the 
+        // prompt field
+        $("#add-property-form").submit(function (e) {
+            var buttons = $("#add-property-dialog").dialog( "option", "buttons" );
+            buttons[0].click();
+            return false;
+        })
+        .validate({
+            rules: {
+                "name": "required"
+            }/*,
+            messages: {
+            }*/
+        });
+        
+        //attach a member selection dialog
+        $('a#add_member').click( function(e) {
+            //initialize the dialog
+            $("#add-member-dialog").dialog({
+                autoOpen: false,
+                height: 'auto',
+                width: 350,
+                modal: true,
+                resizable: false,
+                buttons: [
+                    {
+                        text: UserManager.messages["button.add"],
+                        click: function() {
+                            var form, name, label, itemHtml, newItem, item;
+                            
+                            form = $("#add-group-member-form");
+                            //client side validation
+                            if (!form.valid()) {
+                                return false;
+                            }
+                        
+                            //get the selected member info
+                            name = $("#memberName").val();
+                            label = name;
+                            item = $("#memberName").data("item");
+                            if (item) {
+                                if (item.label && item.value == name) {
+                                    label = item.label;
+                                }
+                            }
+                            
+                            //inject a new member item into the page
+                            itemHtml = '<li><input type="hidden" name=":member" value="' + name + '" /><span>' + label + '</span> <a href="#" class="remove-member" title="' + UserManager.messages['tooltip.removeMember'] + '"><span class="ui-icon ui-icon-circle-close"></span></a></li>';
+                            //not empty, so remove the empty message if it is there
+                            $("#declaredMembers__empty").hide();
+                            $("#declaredMembers").append(itemHtml);
+                            
+                            newItem = $("#declaredMembers").find('li').last();
+                            
+                            //add hover states on the remove member icons
+                            newItem.find('a.remove-member').hover(
+                                function() { $(this).addClass('ui-state-hover'); }, 
+                                function() { $(this).removeClass('ui-state-hover'); }
+                            ).click(
+                                function(e) {
+                                    var memberItem = $(e.currentTarget.parentNode);
+                                    memberItem.hide('slow', function() {
+                                        //haven't submittted to the server yet, so just remove the item from the page
+                                        memberItem.remove();
+                                        if ($('ol#declaredMembers li:visible').length == 0) {
+                                            //after removing the member, the list is empty, so
+                                            // show the empty message.
+                                            $("#declaredMembers__empty").show();
+                                        }
+                                    });
+                                    return false;
+                                }
+                            );
+                            
+                            //close the dialog
+                            $("#add-member-dialog").dialog( "close" );
+                            return false;
+                        }
+                    }
+                ]
+            });
+            
+            //clear old member value
+            $("#memberName").val('');
+            
+            //open the dialog
+            $('#add-member-dialog').dialog('open');
+            return false;
+        });
+
+        //forward the form submit event to the button handler to handle 'Enter' key in the 
+        // prompt field
+        $("#add-group-member-form").submit(function (e) {
+            var buttons = $("#add-member-dialog").dialog( "option", "buttons" );
+            buttons[0].click();
+            return false;
+        })
+        .validate({
+            rules: {
+                ":member": "required"
+            }/*,
+            messages: {
+            }*/
+        });
+
+        //attach an autocomplete handler to the member name field in
+        // the add member dialog
+        $( "#memberName" ).autocomplete({
+            source: UserManager.contextPath + "/system/userManager.autocomplete.json",
+            minLength: 1,
+            select: function(event, ui) {
+                var item = ui.item;
+                $("#memberName")
+                    .val(item.value)
+                    .data("item", item);
+            }
+        })
+        .data( "autocomplete" )._renderItem = function( ul, item ) {
+            return $( "<li></li>" )
+                .data( "item.autocomplete", item )
+                .append( "<a>" + (item.label ? (item.label + " (" + item.value + ")") : item.value) + "</a>" )
+                .appendTo( ul );
+        };        
+    }
+};
+
+
+/**
+ * Holds some common functions for User related pages 
+ */
+UserManager.User = {
+        
+};
+
+/**
+ * For the User create page.
+ */
+UserManager.User.Create = {
+    /**
+     * Initializes the elements for the create User page
+     */
+    init: function() {
+        //apply jquery-ui styles to the create button
+        $('button#createUserBtn').button();
+
+        // validate form
+        /*var validator = */$("#create-user-form").validate({
+            rules: {
+                ":name": "required",
+                "pwd": "required",
+                "pwdConfirm": {
+                      equalTo: "#pwd"
+                }
+            }/*,
+            messages: {
+            }*/
+        });
+        
+        //attach event handler to the create button
+        $('button#createUserBtn').click( function(e) {
+            var form, actionUrl, formData;
+            
+            form = $("#create-user-form");
+            
+            //client side validation
+            if (!form.valid()) {
+                return false;
+            }
+            
+            actionUrl = form.attr('action');
+
+            //switch to a json response
+            actionUrl = actionUrl.substring(0, actionUrl.length - 4) + "json";
+
+            //turn off redirect in this context
+            $('#redirect').attr('disabled', true);
+            formData = form.serialize();
+            $('#redirect').removeAttr('disabled');
+
+            //hide the info msg from a previous action
+            $("#create-user-body div.info-msg-block").hide();
+
+            //submit the create request
+            $.ajax({
+                url: actionUrl,
+                type: 'POST',
+                data: formData,
+                success: function( data, textStatus, xmlHttpRequest ) {
+                    //clear the inputs
+                    $("#create-user-form input[type='text']").val('');
+                    $("#create-user-form input[type='password']").val('');
+    
+                    //inject a success message
+                    $("#create-user-body span.info-msg-text").html(UserManager.messages["user.created.msg"]);
+                    $("#create-user-body div.info-msg-block").show();
+                },
+                error: UserManager.ErrorDlg.errorHandler
+            });
+            return false;
+        });
+    }
+};
+
+/**
+ * For the User update page.
+ */
+UserManager.User.Update = {
+    /**
+     * Initializes the elements for the User update page
+     */
+    init: function() {
+        //apply jquery-ui styles to the update button
+        $('button#updateUserBtn').button();
+        
+        // validate form
+        /*var validator = */$("#update-user-form").validate({
+            rules: {
+            }/*,
+            messages: {
+            }*/
+        });
+        
+        //hover states on the remove member icons
+        $('.remove-property').hover(
+            function() { $(this).addClass('ui-state-hover'); }, 
+            function() { $(this).removeClass('ui-state-hover'); }
+        ).click(
+            function(e) {
+                var memberItem, input, key;
+                
+                //mark the member for removal
+                memberItem = $(e.currentTarget.parentNode);
+                memberItem.hide('slow');
+                input = memberItem.find('input');
+                key = input.attr("name");
+                input.attr("name", key + "@Delete");
+                return false;
+            }
+        );
+        
+        //attach the event handler to the update button
+        $('button#updateUserBtn').click( function(e) {
+            var form, actionUrl, formData;
+            
+            form = $("#update-user-form");
+
+            //client side validation
+            if (!form.valid()) {
+                return false;
+            }
+
+            actionUrl = form.attr('action');
+
+            //switch to a json response
+            actionUrl = actionUrl.substring(0, actionUrl.length - 4) + "json";
+
+            //turn off redirect in this context
+            $('#redirect').attr('disabled', true);
+            formData = form.serialize();
+            $('#redirect').removeAttr('disabled');
+
+            //hide the info msg from a previous action
+            $("#update-user-body div.info-msg-block").hide();
+
+            //submit the update request
+            $.ajax({
+                url: actionUrl,
+                type: 'POST',
+                data: formData,
+                success: function( data, textStatus, xmlHttpRequest ) {
+                    //reload the update body content
+                    $("#content").load(UserManager.contextPath + data.path + ".update_body.html", function() {
+                        //inject a success message
+                        $("#update-user-body span.info-msg-text").html(UserManager.messages["user.updated.msg"]);
+                        $("#update-user-body div.info-msg-block").show();
+                    });
+
+                    setTimeout(function() {
+                        //re-init the page since we just replaced the body
+                        UserManager.User.Update.init();
+
+                        //make visible any elements that require scripting to be enabled 
+                        $(".noscript-hide").removeClass("noscript-hide");
+                    }, 100);
+                },
+                error: UserManager.ErrorDlg.errorHandler
+            });
+            return false;
+        });
+        
+        //attach a confirmation dialog to the 'Remove' link
+        $('a#removeUserLink').click( function(e) {
+            //prepare the confirmation dialog
+            $("#remove-user-dialog").dialog({
+                autoOpen: false,
+                height: 'auto',
+                width: 350,
+                modal: true,
+                resizable: false,
+                buttons: [
+                    {
+                        text: UserManager.messages["confirm.yes"],
+                        click: function() {
+                            $("#remove-user-form").submit();
+                        } 
+                    },
+                    {
+                        text: UserManager.messages["confirm.no"],
+                        click: function() {
+                            $("#remove-user-dialog").dialog("close");
+                        } 
+                    }
+                ]
+            });
+
+            //open the dialog
+            $('#remove-user-dialog').dialog('open');
+            return false;
+        });
+
+        //attach a prompt dialog to the 'Add Property' link
+        $('a#add_property').click( function(e) {
+            //prepare the dialog
+            $("#add-property-dialog").dialog({
+                autoOpen: false,
+                height: 'auto',
+                width: 350,
+                modal: true,
+                resizable: false,
+                buttons: [
+                    {
+                        text: UserManager.messages["button.add"],
+                        click: function() {
+                            var form, name, label, newItem;
+                            
+                            form = $("#add-property-form");
+                            //client side validation
+                            if (!form.valid()) {
+                                return false;
+                            }
+                            
+                            name=$("#newPropName").val();
+                            label = name;
+                            $("#updateSubmitBtns").before('<div class="prop-line ui-helper-clearfix"><label for="' + name + '">' + label + ':</label> <input id="' + name + '" type="text" name="' + name + '" /> <a href="#" class="remove-property" title="' + UserManager.messages["tooltip.removeProperty"] + '"><span class="ui-icon ui-icon-circle-close"></span></a></div>');
+
+                            newItem = $("#updateSubmitBtns").prev();
+                            
+                            //add hover states on the remove property icons
+                            newItem.find('a.remove-property').hover(
+                                function() { $(this).addClass('ui-state-hover'); }, 
+                                function() { $(this).removeClass('ui-state-hover'); }
+                            ).click(
+                                function(e) {
+                                    var propItem = $(e.currentTarget.parentNode);
+                                    propItem.hide('slow', function() {
+                                        propItem.remove();
+                                    });
+                                    return false;
+                                }
+                            );
+                            
+                            $("#add-property-dialog").dialog( "close" );
+                            
+                            newItem.find('input').focus();
+                        } 
+                    }
+                ]
+            });
+            
+            
+            //clear the old value (if any)
+            $("#newPropName").val('');
+            
+            //open the dialog
+            $('#add-property-dialog').dialog('open');
+            return false;
+        });
+
+        //forward the form submit event to the button handler to handle 'Enter' key in the 
+        // prompt field
+        $("#add-property-form").submit(function (e) {
+            var buttons = $("#add-property-dialog").dialog( "option", "buttons" );
+            buttons[0].click();
+            return false;
+        })
+        .validate({    
+            rules: {
+                "name": "required"
+            }/*,
+            messages: {
+            }*/
+        });
+    }
+};
+
+/**
+ * For the User update password page.
+ */
+UserManager.User.UpdatePassword = {
+    /**
+     * Initializes the elements for the User update password page
+     */
+    init: function() {
+        //apply jquery-ui styles to the update button
+        $('button#updatePasswordBtn').button();
+
+        // validate form
+        /*var validator = */$("#update-password-form").validate({
+            rules: {
+                "oldPwd": "required",
+                "newPwd": "required",
+                "newPwdConfirm": {
+                      equalTo: "#newPwd"
+                }
+            }/*,
+            messages: {
+            }*/
+        });
+        
+        //clear input values if the browser auto-filled them.
+        $("#update-password-form input[type='password']").val("");
+        
+        //attach event handler to the update button
+        $('button#updatePasswordBtn').click( function(e) {
+            var form, actionUrl, formData;
+            
+            form = $("#update-password-form");
+
+            //client side validation
+            if (!form.valid()) {
+                return false;
+            }
+            
+            actionUrl = form.attr('action');
+
+            //switch to a json response
+            actionUrl = actionUrl.substring(0, actionUrl.length - 4) + "json";
+
+            //turn off redirect in this context
+            $('#pwdRedirect').attr('disabled', true);
+            formData = form.serialize();
+            $('#pwdRedirect').removeAttr('disabled');
+
+            //hide the info msg from a previous action
+            $("#update-password-body div.info-msg-block").hide();
+
+            //submit the update request
+            $.ajax({
+                url: actionUrl,
+                type: 'POST',
+                data: formData,
+                success: function( data, textStatus, xmlHttpRequest ) {
+                    //clear the inputs
+                    $("#update-password-form input[type='password']").val('');
+    
+                    //inject a success message
+                    $("#update-password-body span.info-msg-text").html(UserManager.messages["user.pwd.updated.msg"]);
+                    $("#update-password-body div.info-msg-block").show();
+                },
+                error: UserManager.ErrorDlg.errorHandler
+            });
+            return false;
+        });
+    }
+};
+
+
+/**
+ * Initialize any objects that are active on the current page
+ */
+$(function() {
+    //make visible any elements that require scripting to be enabled 
+    $(".noscript-hide").removeClass("noscript-hide");
+    
+    if ($("#sidebar-nav").length > 0) {
+        UserManager.SideBar.init();
+    }
+    
+    if ($("#find-authorizables-form").length > 0) {
+        UserManager.Authorizables.init();
+    }
+    
+    if ($("#update-group-form").length > 0) {
+        UserManager.Group.Update.init();
+    }
+    
+    if ($("#create-group-form").length > 0) {
+        UserManager.Group.Create.init();
+    }
+    
+    if ($("#update-user-form").length > 0) {
+        UserManager.User.Update.init();
+    }
+    
+    if ($("#update-password-form").length > 0) {
+        UserManager.User.UpdatePassword.init();
+    }
+    
+    if ($("#create-user-form").length > 0) {
+        UserManager.User.Create.init();
+    }
+});

Propchange: sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.min.js
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.min.js?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.min.js (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.min.js Sun May  1 22:46:46 2011
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+UserManager={contextPath:"",formatMsg:function(c,a){var b=/{(\d+)}/g;
+return c.replace(b,function(){var d=parseInt(arguments[1]);
+return a[d]
+})
+},messages:{"error.dlg.title":"Error","confirm.yes":"Yes","confirm.no":"No","button.add":"Add","searching.progress.msg":"Searching, please wait...","tooltip.removeProperty":"Remove Property","tooltip.removeMember":"Remove Member","group.updated.msg":"Updated the group","user.updated.msg":"Updated the user","user.pwd.updated.msg":"Updated the password","group.created.msg":"Created the group","user.created.msg":"Created the user"}};
+UserManager.SideBar={init:function(){var c,b,a,d,e;
+b=$("ul#sidebar-nav li a");
+a=location.href;
+d=location.hash;
+if(d!=null&&d.length>0){a=a.substring(0,a.length-d.length)
+}for(c=0;
+c<b.length;
+c++){e=b[c];
+if(a==e.href){$(e.parentNode).addClass("ui-corner-all ui-state-highlight")
+}}}};
+UserManager.ErrorDlg={showError:function(b,a){if($("#error_dialog").length==0){$("body").append('<div id="error_dialog" style="display:none;"></div>')
+}$("#error_dialog").html(a);
+$("#error_dialog").dialog({title:b,bgiframe:true,autoOpen:false,width:400,maxHeight:500,modal:true});
+$("#error_dialog").dialog("open")
+},errorHandler:function(d,g,c){var f,b;
+try{f=UserManager.messages["error.dlg.title"];
+b=$.parseJSON(d.responseText);
+if(b.error){UserManager.ErrorDlg.showError(f,b.error.message)
+}else{UserManager.ErrorDlg.showError(f,d.responseText)
+}}catch(a){UserManager.ErrorDlg.showError(f,d.responseText)
+}}};
+UserManager.Authorizables={progressFnId:null,init:function(){$("#find-authorizables-quick-nav").buttonset().show();
+UserManager.Authorizables.applyResultStylesAndHandlers();
+$('#find-authorizables-quick-nav input[type = "radio"]').change(function(a){$("#searchOffset").val(0);
+UserManager.Authorizables.runSearchFn();
+return false
+});
+$("button#findAuthorizablesBtn").button();
+$("button#findAuthorizablesBtn").click(function(a){if($("#findAuthorizablesQuery").val()==""){$("#radioAll").attr("checked",true);
+$("#radioAll").button("refresh")
+}else{$("#radioNone").attr("checked",true);
+$("#radioNone").button("refresh")
+}$("#searchOffset").val(0);
+UserManager.Authorizables.runSearchFn();
+return false
+});
+$(window).bind("hashchange",UserManager.Authorizables.runSearchFromHashFn);
+$(window).trigger("hashchange")
+},progressFn:function(){$("#authorizables-results-body").after('<div id="authorizables-results-progress" style="text-align:center"><img src="'+UserManager.contextPath+'/css/usermgmt/images/ajax-loader.gif" alt="'+UserManager.messages["searching.progress.msg"]+'"/></div>');
+UserManager.Authorizables.progressFnId=null
+},clearProgressFn:function(){if(UserManager.Authorizables.progressFnId!=null){clearTimeout(UserManager.Authorizables.progressFnId);
+UserManager.Authorizables.progressFnId=null
+}$("#authorizables-results-progress").remove()
+},runSearchFn:function(c){var a,b;
+$("#searchOffset").val(c==undefined?"0":c);
+a=$("#find-authorizables-form");
+b=a.serialize();
+window.location.hash=b
+},parseHashParams:function(){var c={},h,b=/\+/g,f=/([^&;=]+)=?([^&;]*)/g,i=function(a){return decodeURIComponent(a.replace(b," "))
+},g=window.location.hash.substring(1);
+while(h=f.exec(g)){c[i(h[1])]=i(h[2])
+}return c
+},runSearchFromHashFn:function(){var b,c,a;
+b=$("#find-authorizables-form");
+c=b.attr("action");
+c=c.substring(0,c.length-4)+"searchresult.html";
+a=UserManager.Authorizables.parseHashParams();
+$("#findAuthorizablesQuery").val(a.q==undefined?"":a.q);
+$('#find-authorizables-quick-nav input[value="'+(a.sp==undefined?"":a.sp)+'"]').attr("checked",true).button("refresh");
+$("#searchOffset").val(a.o==undefined?"0":a.o);
+if(a.q==undefined&&a.sp==undefined){if($("#search-result-ready-to-search").length==0){$.ajax({url:c,type:"get",success:UserManager.Authorizables.searchDoneFn,error:UserManager.ErrorDlg.errorHandler})
+}return
+}$("#authorizables-results-body").hide();
+UserManager.Authorizables.clearProgressFn();
+UserManager.Authorizables.progressFnId=setTimeout(UserManager.Authorizables.progressFn,200);
+$.ajax({url:c,type:"get",data:b.serialize(),cache:false,success:UserManager.Authorizables.searchDoneFn,error:function(e,f,d){UserManager.Authorizables.clearProgressFn();
+UserManager.ErrorDlg.errorHandler(e,f,d)
+}})
+},searchDoneFn:function(a,c,b){UserManager.Authorizables.clearProgressFn();
+$("#authorizables-results-body").replaceWith(a);
+UserManager.Authorizables.applyResultStylesAndHandlers()
+},applyResultStylesAndHandlers:function(a,c,b){$("#search-result-body tr").mouseover(function(){$(this).addClass("ui-state-highlight")
+}).mouseout(function(){$(this).removeClass("ui-state-highlight")
+}).click(function(){var d=$(this).find("td a")[0].href;
+window.location=d;
+return false
+});
+$("#first_page").button().click(function(){UserManager.Authorizables.runSearchFn(0);
+return false
+});
+$("#prev_page").button().click(function(){UserManager.Authorizables.runSearchFn($("#prev_page").val());
+return false
+});
+$("#next_page").button().click(function(){UserManager.Authorizables.runSearchFn($("#next_page").val());
+return false
+})
+}};
+UserManager.Group={};
+UserManager.Group.Create={init:function(){$("button#createGroupBtn").button();
+$("#create-group-form").validate({rules:{":name":"required"}});
+$("button#createGroupBtn").click(function(d){var b,a,c;
+b=$("#create-group-form");
+if(!b.valid()){return false
+}a=b.attr("action");
+a=a.substring(0,a.length-4)+"json";
+$("#redirect").attr("disabled",true);
+c=b.serialize();
+$("#redirect").removeAttr("disabled");
+$("#create-group-body div.info-msg-block").hide();
+$.ajax({url:a,type:"POST",data:c,success:function(e,g,f){$("#create-group-form input[type='text']").val("");
+$("#create-group-body span.info-msg-text").html(UserManager.messages["group.created.msg"]);
+$("#create-group-body div.info-msg-block").show()
+},error:UserManager.ErrorDlg.errorHandler});
+return false
+})
+}};
+UserManager.Group.Update={init:function(){$("button#updateGroupBtn").button();
+$("#update-group-form").validate({rules:{}});
+$(".remove-member").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(b){var a=$(b.currentTarget.parentNode);
+a.hide("slow",function(){if($("ol#declaredMembers li:visible").length==0){$("#declaredMembers__empty").show()
+}});
+a.find("input").attr("name",":member@Delete");
+return false
+});
+$(".remove-property").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(d){var c,a,b;
+c=$(d.currentTarget.parentNode);
+c.hide("slow");
+a=c.find("input");
+b=a.attr("name");
+a.attr("name",b+"@Delete");
+return false
+});
+$("button#updateGroupBtn").click(function(d){var b,a,c;
+b=$("#update-group-form");
+if(!b.valid()){return false
+}a=b.attr("action");
+a=a.substring(0,a.length-4)+"json";
+$("#redirect").attr("disabled",true);
+c=b.serialize();
+$("#redirect").removeAttr("disabled");
+$("#update-group-body div.info-msg-block").hide();
+$.ajax({url:a,type:"POST",data:c,success:function(e,g,f){$("#content").load(UserManager.contextPath+e.path+".update_body.html",function(){$("#update-group-body span.info-msg-text").html(UserManager.messages["group.updated.msg"]);
+$("#update-group-body div.info-msg-block").show()
+});
+setTimeout(function(){UserManager.Group.Update.init();
+$(".noscript-hide").removeClass("noscript-hide")
+},100)
+},error:UserManager.ErrorDlg.errorHandler});
+return false
+});
+$("a#removeGroupLink").click(function(a){$("#remove-group-dialog").dialog({autoOpen:false,height:"auto",width:350,modal:true,resizable:false,buttons:[{text:UserManager.messages["confirm.yes"],click:function(){$("#remove-group-form").submit()
+}},{text:UserManager.messages["confirm.no"],click:function(){$("#remove-group-dialog").dialog("close")
+}}]});
+$("#remove-group-dialog").dialog("open");
+return false
+});
+$("a#add_property").click(function(a){$("#add-property-dialog").dialog({autoOpen:false,height:"auto",width:350,modal:true,resizable:false,buttons:[{text:UserManager.messages["button.add"],click:function(){var e,c,b,d;
+e=$("#add-property-form");
+if(!e.valid()){return false
+}c=$("#newPropName").val();
+b=c;
+$("#updateSubmitBtns").before('<div class="prop-line ui-helper-clearfix"><label for="'+c+'">'+b+':</label> <input id="'+c+'" type="text" name="'+c+'" /> <a href="#" class="remove-property" title="'+UserManager.messages["tooltip.removeProperty"]+'"><span class="ui-icon ui-icon-circle-close"></span></a></div>');
+d=$("#updateSubmitBtns").prev();
+d.find("a.remove-property").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(f){var g=$(f.currentTarget.parentNode);
+g.hide("slow",function(){g.remove()
+});
+return false
+});
+$("#add-property-dialog").dialog("close");
+d.find("input").focus()
+}}]});
+$("#newPropName").val("");
+$("#add-property-dialog").dialog("open");
+return false
+});
+$("#add-property-form").submit(function(b){var a=$("#add-property-dialog").dialog("option","buttons");
+a[0].click();
+return false
+}).validate({rules:{name:"required"}});
+$("a#add_member").click(function(a){$("#add-member-dialog").dialog({autoOpen:false,height:"auto",width:350,modal:true,resizable:false,buttons:[{text:UserManager.messages["button.add"],click:function(){var f,c,b,g,d,e;
+f=$("#add-group-member-form");
+if(!f.valid()){return false
+}c=$("#memberName").val();
+b=c;
+e=$("#memberName").data("item");
+if(e){if(e.label&&e.value==c){b=e.label
+}}g='<li><input type="hidden" name=":member" value="'+c+'" /><span>'+b+'</span> <a href="#" class="remove-member" title="'+UserManager.messages["tooltip.removeMember"]+'"><span class="ui-icon ui-icon-circle-close"></span></a></li>';
+$("#declaredMembers__empty").hide();
+$("#declaredMembers").append(g);
+d=$("#declaredMembers").find("li").last();
+d.find("a.remove-member").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(i){var h=$(i.currentTarget.parentNode);
+h.hide("slow",function(){h.remove();
+if($("ol#declaredMembers li:visible").length==0){$("#declaredMembers__empty").show()
+}});
+return false
+});
+$("#add-member-dialog").dialog("close");
+return false
+}}]});
+$("#memberName").val("");
+$("#add-member-dialog").dialog("open");
+return false
+});
+$("#add-group-member-form").submit(function(b){var a=$("#add-member-dialog").dialog("option","buttons");
+a[0].click();
+return false
+}).validate({rules:{":member":"required"}});
+$("#memberName").autocomplete({source:UserManager.contextPath+"/system/userManager.autocomplete.json",minLength:1,select:function(b,c){var a=c.item;
+$("#memberName").val(a.value).data("item",a)
+}}).data("autocomplete")._renderItem=function(a,b){return $("<li></li>").data("item.autocomplete",b).append("<a>"+(b.label?(b.label+" ("+b.value+")"):b.value)+"</a>").appendTo(a)
+}
+}};
+UserManager.User={};
+UserManager.User.Create={init:function(){$("button#createUserBtn").button();
+$("#create-user-form").validate({rules:{":name":"required",pwd:"required",pwdConfirm:{equalTo:"#pwd"}}});
+$("button#createUserBtn").click(function(d){var b,a,c;
+b=$("#create-user-form");
+if(!b.valid()){return false
+}a=b.attr("action");
+a=a.substring(0,a.length-4)+"json";
+$("#redirect").attr("disabled",true);
+c=b.serialize();
+$("#redirect").removeAttr("disabled");
+$("#create-user-body div.info-msg-block").hide();
+$.ajax({url:a,type:"POST",data:c,success:function(e,g,f){$("#create-user-form input[type='text']").val("");
+$("#create-user-form input[type='password']").val("");
+$("#create-user-body span.info-msg-text").html(UserManager.messages["user.created.msg"]);
+$("#create-user-body div.info-msg-block").show()
+},error:UserManager.ErrorDlg.errorHandler});
+return false
+})
+}};
+UserManager.User.Update={init:function(){$("button#updateUserBtn").button();
+$("#update-user-form").validate({rules:{}});
+$(".remove-property").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(d){var c,a,b;
+c=$(d.currentTarget.parentNode);
+c.hide("slow");
+a=c.find("input");
+b=a.attr("name");
+a.attr("name",b+"@Delete");
+return false
+});
+$("button#updateUserBtn").click(function(d){var b,a,c;
+b=$("#update-user-form");
+if(!b.valid()){return false
+}a=b.attr("action");
+a=a.substring(0,a.length-4)+"json";
+$("#redirect").attr("disabled",true);
+c=b.serialize();
+$("#redirect").removeAttr("disabled");
+$("#update-user-body div.info-msg-block").hide();
+$.ajax({url:a,type:"POST",data:c,success:function(e,g,f){$("#content").load(UserManager.contextPath+e.path+".update_body.html",function(){$("#update-user-body span.info-msg-text").html(UserManager.messages["user.updated.msg"]);
+$("#update-user-body div.info-msg-block").show()
+});
+setTimeout(function(){UserManager.User.Update.init();
+$(".noscript-hide").removeClass("noscript-hide")
+},100)
+},error:UserManager.ErrorDlg.errorHandler});
+return false
+});
+$("a#removeUserLink").click(function(a){$("#remove-user-dialog").dialog({autoOpen:false,height:"auto",width:350,modal:true,resizable:false,buttons:[{text:UserManager.messages["confirm.yes"],click:function(){$("#remove-user-form").submit()
+}},{text:UserManager.messages["confirm.no"],click:function(){$("#remove-user-dialog").dialog("close")
+}}]});
+$("#remove-user-dialog").dialog("open");
+return false
+});
+$("a#add_property").click(function(a){$("#add-property-dialog").dialog({autoOpen:false,height:"auto",width:350,modal:true,resizable:false,buttons:[{text:UserManager.messages["button.add"],click:function(){var e,c,b,d;
+e=$("#add-property-form");
+if(!e.valid()){return false
+}c=$("#newPropName").val();
+b=c;
+$("#updateSubmitBtns").before('<div class="prop-line ui-helper-clearfix"><label for="'+c+'">'+b+':</label> <input id="'+c+'" type="text" name="'+c+'" /> <a href="#" class="remove-property" title="'+UserManager.messages["tooltip.removeProperty"]+'"><span class="ui-icon ui-icon-circle-close"></span></a></div>');
+d=$("#updateSubmitBtns").prev();
+d.find("a.remove-property").hover(function(){$(this).addClass("ui-state-hover")
+},function(){$(this).removeClass("ui-state-hover")
+}).click(function(f){var g=$(f.currentTarget.parentNode);
+g.hide("slow",function(){g.remove()
+});
+return false
+});
+$("#add-property-dialog").dialog("close");
+d.find("input").focus()
+}}]});
+$("#newPropName").val("");
+$("#add-property-dialog").dialog("open");
+return false
+});
+$("#add-property-form").submit(function(b){var a=$("#add-property-dialog").dialog("option","buttons");
+a[0].click();
+return false
+}).validate({rules:{name:"required"}})
+}};
+UserManager.User.UpdatePassword={init:function(){$("button#updatePasswordBtn").button();
+$("#update-password-form").validate({rules:{oldPwd:"required",newPwd:"required",newPwdConfirm:{equalTo:"#newPwd"}}});
+$("#update-password-form input[type='password']").val("");
+$("button#updatePasswordBtn").click(function(d){var b,a,c;
+b=$("#update-password-form");
+if(!b.valid()){return false
+}a=b.attr("action");
+a=a.substring(0,a.length-4)+"json";
+$("#pwdRedirect").attr("disabled",true);
+c=b.serialize();
+$("#pwdRedirect").removeAttr("disabled");
+$("#update-password-body div.info-msg-block").hide();
+$.ajax({url:a,type:"POST",data:c,success:function(e,g,f){$("#update-password-form input[type='password']").val("");
+$("#update-password-body span.info-msg-text").html(UserManager.messages["user.pwd.updated.msg"]);
+$("#update-password-body div.info-msg-block").show()
+},error:UserManager.ErrorDlg.errorHandler});
+return false
+})
+}};
+$(function(){$(".noscript-hide").removeClass("noscript-hide");
+if($("#sidebar-nav").length>0){UserManager.SideBar.init()
+}if($("#find-authorizables-form").length>0){UserManager.Authorizables.init()
+}if($("#update-group-form").length>0){UserManager.Group.Update.init()
+}if($("#create-group-form").length>0){UserManager.Group.Create.init()
+}if($("#update-user-form").length>0){UserManager.User.Update.init()
+}if($("#update-password-form").length>0){UserManager.User.UpdatePassword.init()
+}if($("#create-user-form").length>0){UserManager.User.Create.init()
+}});
\ No newline at end of file

Propchange: sling/trunk/samples/usermanager-ui/src/main/resources/js/usermanager/usermanager.min.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,41 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+var authorizable = resource.adaptTo(Packages.org.apache.jackrabbit.api.security.user.Authorizable);
+var privilegesInfo = sling.getService(Packages.org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo);
+var canEdit = privilegesInfo.canUpdateProperties(currentSession, authorizable.getID());
+
+//header options
+request.setAttribute("page.title", rb.getString(canEdit ? "page.title.update.group" : "page.title.view.group"));
+
+//page sidebar template
+request.setAttribute("sidebar.template", resource.path + ".sidebar.html");
+request.setAttribute("sidebar.template.options", "sling/usermgmt");
+
+//page body template
+request.setAttribute("body.template", resource.path + ".update_body.html");
+request.setAttribute("body.template.options", null);
+
+//override the logout target since the anonymous user usually can't view groups
+request.setAttribute("logout.target", request.contextPath + "/system/userManager/group.html");
+
+//render the page using the default page template
+sling.include(resource.path + ".page.html", "sling/usermgmt");
+%>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/update_body.html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/update_body.html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/update_body.html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/group/update_body.html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,196 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var privilegesInfo = sling.getService(Packages.org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo);
+var authorizable = resource.adaptTo(Packages.org.apache.jackrabbit.api.security.user.Authorizable);
+var canEdit = privilegesInfo.canUpdateProperties(currentSession, authorizable.getID());
+var canModifyMembers = privilegesInfo.canUpdateGroupMembers(currentSession, authorizable.getID()); 
+var canRemove = privilegesInfo.canRemove(currentSession, authorizable.getID()); 
+var valueMap = resource.adaptTo(Packages.org.apache.sling.api.resource.ValueMap);
+
+var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+var propNameSet = new Packages.java.util.TreeSet(valueMap.keySet());
+propNameSet.remove("declaredMemberOf");
+propNameSet.remove("members");
+propNameSet.remove("declaredMembers");
+propNameSet.remove("memberOf");
+
+var propKeysCsv = rb.getString("csv.static.group.prop.keys");
+var items = [];
+if (propKeysCsv != null && propKeysCsv.length() > 0 && !propKeysCsv.equals("csv.static.group.prop.keys")) {
+    items = propKeysCsv.split(",");
+}
+for (var i=0; i < items.length; i++) {
+    propNameSet.add(items[i]);
+}
+
+function propLabel(propName) {
+    var key = "prop.label." + propName;
+    var value = rb.getString(key);
+    if (value == key) {
+        return propName;
+    }
+    return value;
+};
+function format(key, args) {
+    var value = rb.getString(key);
+    return Packages.java.text.MessageFormat.format(value, args);
+}
+function displayName(path) {
+    var res = request.getResourceResolver().resolve(path);
+    var resValueMap = res.adaptTo(Packages.org.apache.sling.api.resource.ValueMap);
+    var value = resValueMap.get("displayName");
+    if (value == null) {
+        value = path.substring(path.lastIndexOf('/') + 1)       
+    }
+    return value;
+}
+%>
+<div class="ui-widget ui-widget-content ui-corner-all usermgmt-body" id="update-group-body" >
+    <h3 class="ui-widget-header ui-corner-all usermgmt-header"><%=format(canEdit ? "header.update.group" : "header.view.group", authorizable.getID())%></h3>
+    
+    <div class="info-msg-block" style="display:none;">
+        <div class="ui-state-highlight ui-corner-all"> 
+            <p>
+                <span class="ui-icon ui-icon-info"></span>
+                <span class="info-msg-text"></span>
+            </p>
+        </div>
+    </div>    
+    
+    <form id="update-group-form" accept-charset="UTF-8" 
+            action="<%=request.contextPath%><%=resource.path %>.update.html" 
+            method="post">
+        <fieldset>
+            <input type="hidden" value="UTF-8" name="_charset_" />
+            <input id="redirect" type="hidden" name=":redirect" value="<%=request.contextPath%><%=resource.path %>.html" />
+
+            <%-- Declared Members --%>
+            <% var key = "declaredMembers";
+               var value = valueMap.get(key);
+            %>
+            <div class="prop-line ui-helper-clearfix">
+                <label for="<%=key%>"><%=propLabel(key)%>:</label>
+
+                <ol id="<%=key%>">
+                    <li id="<%=key%>__empty" <%= value.length == 0 ? "" : "style='display:none'" %>><%=rb.getString("declaredMembers.empty")%></li>
+                    <%                      
+                        for (i = 0; i < value.length; i++) {
+                          var group = value[i];
+                    %>                            
+                        <li>
+                            <a href="<%=request.contextPath%><%=group%>.html"><%=displayName(group)%></a>
+                            <% if (canModifyMembers) { %>
+                            <input type="hidden" name=":member" value="<%=group%>" />
+                            <a href='#' class="noscript-hide remove-member" title='<%=rb.getString("tooltip.removeMember")%>'><span class="ui-icon ui-icon-circle-close"></span></a>
+                            <% } /* endif(canModifyMembers) */ %>
+                        </li>
+                    <%
+                       }/* endfor */
+                    %>
+                </ol>
+            </div>
+            
+            <%-- Member Of --%>
+            <% key = "memberOf"; 
+               value = valueMap.get(key);
+            %>
+            <div class="prop-line ui-helper-clearfix">
+                <label for="<%=key%>"><%=propLabel(key)%>:</label>
+
+                <ol id="<%=key%>">
+                    <li id="<%=key%>__empty" <%= value.length == 0 ? "" : "style='display:none'" %>><%=rb.getString("memberOf.empty")%></li>
+                    <%                      
+                       for (i = 0; i < value.length; i++) {
+                          var group = value[i];
+                    %>                            
+                        <li>
+                            <a href="<%=request.contextPath%><%=group%>.html"><%=displayName(group)%></a>
+                        </li>
+                    <%
+                       }/* endfor */
+                    %>
+                </ol>
+            </div>
+            
+            <%
+                var it = propNameSet.iterator();
+                while (it.hasNext()) {
+                    key = it.next();
+                    value = valueMap.get(key);
+                    if (value == null) {
+                        value = "";
+                    }
+          %>
+            <div class="prop-line ui-helper-clearfix">
+                <label for="<%=key%>"><%=propLabel(key) %>:</label>
+                <input id="<%=key%>" type="text" name="<%=key%>" value='<%=value%>' <%= canEdit ? "" : "disabled=\"disabled\" readonly=\"readonly\" class=\"disabled\""%>/>
+                <% if (canEdit) { %><a href='#' class="noscript-hide remove-property" title='<%=rb.getString("tooltip.removeProperty")%>'><span class="ui-icon ui-icon-circle-close"></span></a><% } %>
+            </div>
+            <%
+                } /* endwhile */
+            %>
+
+            <div id="updateSubmitBtns" class="ui-helper-clearfix">
+                <label>&#160;</label>
+                <% if (canEdit) { %><button accesskey="u" id="updateGroupBtn" type="submit"><%=rb.getString("button.save")%></button><% } %>
+                <span class="noscript-hide">
+                <% if (canRemove) { %><a href="#" id="removeGroupLink"><%=rb.getString("link.remove")%></a><% } %>
+                <% if (canEdit) { %>| <a href="#" id="add_property"><%=rb.getString("link.add.property")%></a><% } %> 
+                <% if (canModifyMembers) { %>| <a href="#" id="add_member"><%=rb.getString("link.add.member")%></a><% } %>
+                </span>
+            </div>
+        </fieldset>
+    </form>
+</div>
+
+<% if (canEdit) { %>
+<div id="add-property-dialog" title='<%=rb.getString("dialog.title.add.property")%>' style="display:none">
+    <form id='add-property-form' action="#">
+    <fieldset>
+        <label for="newPropName"><%=rb.getString("label.property.name")%></label>
+        <input type="text" name="name" id="newPropName" />
+    </fieldset>
+    </form>
+</div>
+<% } /*endif(canEdit) */ %>
+
+<% if (canRemove) { %>
+<div id="remove-group-dialog" title='<%=rb.getString("dialog.title.confirm.remove")%>' style="display:none">
+    <form id='remove-group-form' action="<%=resource.path%>.delete.html" method="post">
+    <fieldset>
+        <input type="hidden" name=":redirect" value="<%=request.contextPath%>/system/userManager/group.html" />
+        <p>
+            <%=rb.getString("msg.group.confirm.remove") %>
+        </p>
+    </fieldset>
+    </form>
+</div>
+<% } /*endif(canRemove) */ %>
+
+<% if (canModifyMembers) { %>
+<div id="add-member-dialog" title='<%=rb.getString("dialog.title.add.member") %>' style="display:none">
+    <form id='add-group-member-form' action="#" >
+    <fieldset>
+        <label for="memberName"><%=rb.getString("label.group.name") %></label>
+        <input type="text" name=":member" id="memberName" />
+    </fieldset>
+    </form>
+</div>
+<% } /*endif(canModifyMembers) */ %>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/body.html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/body.html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/body.html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/body.html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,29 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+var searchType = 2; //search only groups
+request.setAttribute("search.type", searchType);
+
+var title = rb.getString("page.title.find.groups");
+request.setAttribute("page.title", title);
+
+//delegate the 'authorizables' script to render the page
+sling.include(resource.path + ".body.html", "sling/userManager");
+%>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create.html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create.html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create.html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create.html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,40 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var privilegesInfo = sling.getService(Packages.org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo);
+if (!privilegesInfo.canAddGroup(currentSession)) {
+    //user can't create groups.
+    response.sendError(403);
+} else {
+    var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+    //header options
+    request.setAttribute("page.title", rb.getString("page.title.create.group"));
+
+    //page sidebar template
+    request.setAttribute("sidebar.template", resource.path + ".sidebar.html");
+    request.setAttribute("sidebar.template.options", "sling/usermgmt");
+
+    //page body template
+    request.setAttribute("body.template", resource.path + ".create_body.html");
+    //request.setAttribute("body.template.options", null);
+
+    //render the page using the default page template
+    sling.include(resource.path + ".page.html", "sling/usermgmt");
+}
+%>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create_body.html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create_body.html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create_body.html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/create_body.html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,61 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var privilegesInfo = sling.getService(Packages.org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo);
+if (!privilegesInfo.canAddGroup(currentSession)) {
+    //user can't create groups.
+    response.sendError(403);
+} else {
+    var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+%>
+<div class="ui-widget ui-widget-content ui-corner-all usermgmt-body" id="create-group-body" >
+    <h3 class="ui-widget-header ui-corner-all usermgmt-header"><%=rb.getString("page.title.create.group")%></h3>
+    
+    <div class="info-msg-block" style="display:none;">
+        <div class="ui-state-highlight ui-corner-all"> 
+            <p>
+                <span class="ui-icon ui-icon-info"></span>
+                <span class="info-msg-text"></span>
+            </p>
+        </div>
+    </div>    
+    
+    <form id="create-group-form" accept-charset="UTF-8" 
+            action="<%=request.contextPath%><%=resource.path%>.create.html" 
+            method="post">
+        <fieldset>
+            <input type="hidden" value="UTF-8" name="_charset_" />
+
+            <div class="prop-line ui-helper-clearfix">
+                <label for="groupId" accesskey="n"><%=rb.getString("prop.label.groupid")%>:</label>
+                <input id="groupId" type="text" name=":name" />
+            </div>
+
+            <div class="prop-line ui-helper-clearfix">
+                <label for="displayName" accesskey="n"><%=rb.getString("prop.label.displayName")%>:</label>
+                <input id="displayName" type="text" name="displayName" />
+            </div>
+
+            <div class="ui-helper-clearfix">
+                <label>&#160;</label>
+                <button accesskey="r" id="createGroupBtn" type="submit"><%=rb.getString("button.create")%></button>
+            </div>
+        </fieldset>
+    </form>
+</div>
+<% } /*endif (canAddGroup) */ %>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,34 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+//header options
+request.setAttribute("page.title", rb.getString("page.title.find.groups"));
+
+//page sidebar template
+request.setAttribute("sidebar.template", resource.path + ".sidebar.html");
+request.setAttribute("sidebar.template.options", "sling/usermgmt");
+
+//page body template
+request.setAttribute("body.template", resource.path + ".body.html");
+//request.setAttribute("body.template.options", "sling/groups");
+
+//render the page using the default page template
+sling.include(resource.path + ".page.html", "sling/usermgmt");
+%>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/searchresult.html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/searchresult.html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/searchresult.html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/groups/searchresult.html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,24 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var searchType = 2; //search only groups
+request.setAttribute("search.type", searchType);
+
+//delegate the 'authorizables' script to render the page
+sling.include(resource.path + ".searchresult.html", "sling/userManager");
+%>
\ No newline at end of file

Added: sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/user/html.esp
URL: http://svn.apache.org/viewvc/sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/user/html.esp?rev=1098430&view=auto
==============================================================================
--- sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/user/html.esp (added)
+++ sling/trunk/samples/usermanager-ui/src/main/resources/libs/sling/user/html.esp Sun May  1 22:46:46 2011
@@ -0,0 +1,41 @@
+<%
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var rb = request.getResourceBundle("org.apache.sling.usermgr.Resources", null);
+
+var authorizable = resource.adaptTo(Packages.org.apache.jackrabbit.api.security.user.Authorizable);
+var privilegesInfo = sling.getService(Packages.org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo);
+var canEdit = privilegesInfo.canUpdateProperties(currentSession, authorizable.getID());
+
+//header options
+request.setAttribute("page.title", rb.getString(canEdit ? "page.title.update.user" : "page.title.view.user"));
+
+//page sidebar template
+request.setAttribute("sidebar.template", resource.path + ".sidebar.html");
+request.setAttribute("sidebar.template.options", "sling/usermgmt");
+
+//page body template
+request.setAttribute("body.template", resource.path + ".update_body.html");
+request.setAttribute("body.template.options", null);
+
+//override the logout target since the anonymous user usually can't view groups
+request.setAttribute("logout.target", request.contextPath + "/system/userManager/user.html");
+
+//render the page using the default page template
+sling.include(resource.path + ".page.html", "sling/usermgmt");
+%>
\ No newline at end of file