You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ry...@apache.org on 2012/02/23 20:23:12 UTC

svn commit: r1292908 [7/9] - in /lucene/dev/trunk/solr/webapp/web: ./ css/ css/styles/ js/ js/lib/ js/scripts/ tpl/

Added: lucene/dev/trunk/solr/webapp/web/js/scripts/analysis.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/scripts/analysis.js?rev=1292908&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/scripts/analysis.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/scripts/analysis.js Thu Feb 23 19:23:10 2012
@@ -0,0 +1,420 @@
+// #/:core/analysis
+sammy.get
+(
+    /^#\/([\w\d-]+)\/(analysis)$/,
+    function( context )
+    {
+        var core_basepath = this.active_core.attr( 'data-basepath' );
+        var content_element = $( '#content' );
+        
+        $.get
+        (
+            'tpl/analysis.html',
+            function( template )
+            {
+                content_element
+                    .html( template );
+                
+                var analysis_element = $( '#analysis', content_element );
+                var analysis_form = $( 'form', analysis_element );
+                var analysis_result = $( '#analysis-result', analysis_element );
+                analysis_result.hide();
+                
+                $.ajax
+                (
+                    {
+                        url : core_basepath + '/admin/luke?wt=json&show=schema',
+                        dataType : 'json',
+                        context : $( '#type_or_name', analysis_form ),
+                        beforeSend : function( xhr, settings )
+                        {
+                            this
+                                .html( '<option value="">Loading ... </option>' )
+                                .addClass( 'loader' );
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            var content = '';
+                            
+                            var fields = [];
+                            for( var field_name in response.schema.fields )
+                            {
+                                fields.push
+                                (
+                                    '<option value="fieldname=' + field_name + '">' + field_name + '</option>'
+                                );
+                            }
+                            if( 0 !== fields.length )
+                            {
+                                content += '<optgroup label="Fields">' + "\n";
+                                content += fields.sort().join( "\n" ) + "\n";
+                                content += '</optgroup>' + "\n";
+                            }
+                            
+                            var types = [];
+                            for( var type_name in response.schema.types )
+                            {
+                                types.push
+                                (
+                                    '<option value="fieldtype=' + type_name + '">' + type_name + '</option>'
+                                );
+                            }
+                            if( 0 !== types.length )
+                            {
+                                content += '<optgroup label="Types">' + "\n";
+                                content += types.sort().join( "\n" ) + "\n";
+                                content += '</optgroup>' + "\n";
+                            }
+                            
+                            this
+                                .html( content );
+
+                            $( 'option[value="fieldname\=' + response.schema.defaultSearchField + '"]', this )
+                                .attr( 'selected', 'selected' );
+                        },
+                        error : function( xhr, text_status, error_thrown)
+                        {
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                            this
+                                .removeClass( 'loader' );
+                        }
+                    }
+                );
+                        
+                $( '.analysis-error .head a', analysis_element )
+                    .die( 'click' )
+                    .live
+                    (
+                        'click',
+                        function( event )
+                        {
+                            $( this ).parents( '.analysis-error' )
+                                .toggleClass( 'expanded' );
+                        }
+                    );
+                        
+                $( '.verbose_output a', analysis_element )
+                    .die( 'click' )
+                    .live
+                    (
+                        'click',
+                        function( event )
+                        {
+                            $( this ).parent()
+                                .toggleClass( 'active' );
+                            
+                            analysis_result
+                                .toggleClass( 'verbose_output' );
+                            
+                            check_empty_spacer();
+                        }
+                    );
+                
+                var check_empty_spacer = function()
+                {
+                    var spacer_holder = $( 'td.part.data.spacer .holder', analysis_result );
+
+                    if( 0 === spacer_holder.size() )
+                    {
+                        return false;
+                    }
+
+                    var verbose_output = analysis_result.hasClass( 'verbose_output' );
+
+                    spacer_holder
+                        .each
+                        (
+                            function( index, element )
+                            {
+                                element = $( element );
+
+                                if( verbose_output )
+                                {
+                                    var cell = element.parent();
+                                    element.height( cell.height() );
+                                }
+                                else
+                                {
+                                    element.removeAttr( 'style' );
+                                }
+                            }
+                        );
+                }
+
+                var button = $( 'button', analysis_form )
+                
+                analysis_form
+                    .ajaxForm
+                    (
+                        {
+                            url : core_basepath + '/analysis/field?wt=json',
+                            dataType : 'json',
+                            beforeSubmit : function( array, form, options )
+                            {
+                                loader.show( button );
+                                button.attr( 'disabled', true );
+                                
+                                array.push( { name: 'analysis.showmatch', value: 'true' } );
+                                
+                                var type_or_name = $( '#type_or_name', form ).val().split( '=' );
+                                
+                                array.push( { name: 'analysis.' + type_or_name[0], value: type_or_name[1] } );
+                            },
+                            success : function( response, status_text, xhr, form )
+                            {
+                                $( '.analysis-error', analysis_element )
+                                    .hide();
+                                
+                                analysis_result
+                                    .empty()
+                                    .show();
+                                
+                                for( var name in response.analysis.field_names )
+                                {
+                                    build_analysis_table( 'name', name, response.analysis.field_names[name] );
+                                }
+                                
+                                for( var name in response.analysis.field_types )
+                                {
+                                    build_analysis_table( 'type', name, response.analysis.field_types[name] );
+                                }
+
+                                check_empty_spacer();
+                            },
+                            error : function( xhr, text_status, error_thrown )
+                            {
+                                analysis_result
+                                    .empty()
+                                    .hide();
+
+                                if( 404 === xhr.status )
+                                {
+                                    $( '#analysis-handler-missing', analysis_element )
+                                        .show();
+                                }
+                                else
+                                {
+                                    var error_message = error_thrown.match( /^(.+Exception):\s+(.*)$/ );
+
+                                    $( '#analysis-error', analysis_element )
+                                        .show();
+
+                                    $( '#analysis-error .head a span', analysis_element )
+                                        .text( error_message[1] );
+
+                                    $( '#analysis-error .body', analysis_element )
+                                        .text( error_message[2].replace( /(\s+at\s+)/g, " at\n" ) );
+                                }
+                            },
+                            complete : function()
+                            {
+                                loader.hide( $( 'button', analysis_form ) );
+                                button.removeAttr( 'disabled' );
+                            }
+                        }
+                    );
+
+                    var generate_class_name = function( type )
+                    {
+                        var classes = [type];
+                        if( 'text' !== type )
+                        {
+                            classes.push( 'verbose_output' );
+                        }
+                        return classes.join( ' ' );
+                    }
+                    
+                    var build_analysis_table = function( field_or_name, name, analysis_data )
+                    {        
+                        for( var type in analysis_data )
+                        {
+                            var type_length = analysis_data[type].length;
+                            if( 0 !== type_length )
+                            {
+                                var global_elements_count = 0;
+                                for( var i = 0; i < analysis_data[type].length; i += 2 )
+                                {
+                                    if( 'string' === typeof analysis_data[type][i+1] )
+                                    {
+                                        analysis_data[type][i+1] = [{ 'text': analysis_data[type][i+1] }]
+                                    }
+                                    global_elements_count = Math.max( global_elements_count,
+                                                                      analysis_data[type][i+1].length );
+                                }
+
+                                var content = '<div class="' + type + '">' + "\n";
+                                content += '<table border="0" cellspacing="0" cellpadding="0">' + "\n";
+                                
+                                for( var i = 0; i < analysis_data[type].length; i += 2 )
+                                {
+                                    var colspan = 1;
+                                    var elements = analysis_data[type][i+1];
+                                    var elements_count = global_elements_count;
+                                    
+                                    if( !elements[0].positionHistory )
+                                    {
+                                        colspan = elements_count;
+                                        elements_count = 1;
+                                    }
+
+                                    var legend = [];
+                                    for( var key in elements[0] )
+                                    {
+                                        var key_parts = key.split( '#' );
+                                        var used_key = key_parts.pop();
+                                        var short_key = used_key;
+
+                                        if( 1 === key_parts.length )
+                                        {
+                                            used_key = '<abbr title="' + key + '">' + used_key + '</abbr>';
+                                        }
+
+                                        if( 'positionHistory' === short_key || 'match' === short_key )
+                                        {
+                                            continue;
+                                        }
+
+                                        legend.push
+                                        (
+                                            '<tr class="' + generate_class_name( short_key ) + '">' +
+                                            '<td>' + used_key + '</td>' +
+                                            '</tr>'
+                                        );
+                                    }
+
+                                    content += '<tbody>' + "\n";
+                                    content += '<tr class="step">' + "\n";
+
+                                        // analyzer
+                                        var analyzer_name = analysis_data[type][i]
+                                                                .replace( /(\$1)+$/g, '' );
+
+                                        var analyzer_short = -1 !== analyzer_name.indexOf( '$' )
+                                                           ? analyzer_name.split( '$' )[1]
+                                                           : analyzer_name.split( '.' ).pop();
+                                        analyzer_short = analyzer_short.match( /[A-Z]/g ).join( '' );
+
+                                        content += '<td class="part analyzer"><div>' + "\n";
+                                        content += '<abbr title="' + analysis_data[type][i] + '">' + "\n";
+                                        content += analyzer_short + '</abbr></div></td>' + "\n";
+
+                                        // legend
+                                        content += '<td class="part legend"><div class="holder">' + "\n";
+                                        content += '<table border="0" cellspacing="0" cellpadding="0">' + "\n";
+                                        content += '<tr><td>' + "\n";
+                                        content += '<table border="0" cellspacing="0" cellpadding="0">' + "\n";
+                                        content += legend.join( "\n" ) + "\n";
+                                        content += '</table></td></tr></table></td>' + "\n";
+
+                                        // data
+                                        var cell_content = '<td class="part data spacer" '
+                                                         + '    colspan="' + colspan + '">'
+                                                         + '<div class="holder">&nbsp;</div>'
+                                                         + '</td>';
+                                        var cells = new Array( elements_count + 1 ).join( cell_content );
+                                        content += cells + "\n";
+
+                                    content += '</tr>' + "\n";
+                                    content += '</tbody>' + "\n";
+                                }
+                                content += '</table>' + "\n";
+                                content += '</div>' + "\n";
+
+                                $( '.' + type, analysis_result )
+                                    .remove();
+
+                                analysis_result
+                                    .append( content );
+                                
+                                var analysis_result_type = $( '.' + type, analysis_result );
+
+                                for( var i = 0; i < analysis_data[type].length; i += 2 )
+                                {
+                                    for( var j = 0; j < analysis_data[type][i+1].length; j += 1 )
+                                    {
+                                        var pos = analysis_data[type][i+1][j].positionHistory
+                                                ? analysis_data[type][i+1][j].positionHistory[0]
+                                                : 1;
+                                        var selector = 'tr.step:eq(' + ( i / 2 ) +') '
+                                                     + 'td.data:eq(' + ( pos - 1 ) + ') '
+                                                     + '.holder';
+                                        var cell = $( selector, analysis_result_type );
+
+                                        cell.parent()
+                                            .removeClass( 'spacer' );
+
+                                        var table = $( 'table tr.details', cell );
+                                        if( 0 === table.size() )
+                                        {
+                                            cell
+                                                .html
+                                                (
+                                                    '<table border="0" cellspacing="0" cellpadding="0">' + 
+                                                    '<tr class="details"></tr></table>'
+                                                );
+                                            var table = $( 'table tr.details', cell );
+                                        }
+
+                                        var tokens = [];
+                                        for( var key in analysis_data[type][i+1][j] )
+                                        {
+                                            var short_key = key.split( '#' ).pop();
+                                            
+                                            if( 'positionHistory' === short_key || 'match' === short_key )
+                                            {
+                                                continue;
+                                            }
+
+                                            var classes = [];
+                                            classes.push( generate_class_name( short_key ) );
+
+                                            var data = analysis_data[type][i+1][j][key];
+                                            if( 'object' === typeof data && data instanceof Array )
+                                            {
+                                                data = data.join( ' ' );
+                                            }
+                                            if( 'string' === typeof data )
+                                            {
+                                                data = data.esc();
+                                            }
+
+                                            if( null === data || 0 === data.length )
+                                            {
+                                                classes.push( 'empty' );
+                                                data = '&empty;';
+                                            }
+
+                                            if( analysis_data[type][i+1][j].match && 
+                                                ( 'text' === short_key || 'raw_bytes' === short_key ) )
+                                            {
+                                                classes.push( 'match' );
+                                            }
+
+                                            tokens.push
+                                            (
+                                                '<tr class="' + classes.join( ' ' ) + '">' +
+                                                '<td>' + data + '</td>' +
+                                                '</tr>'
+                                            );
+                                        }
+                                        table
+                                            .append
+                                            (
+                                                '<td class="details">' +
+                                                '<table border="0" cellspacing="0" cellpadding="0">' +
+                                                tokens.join( "\n" ) +
+                                                '</table></td>'
+                                            );
+                                    }
+                                }
+                
+                            }
+                        }
+                    }
+                    
+            }
+        );
+    }
+);

Added: lucene/dev/trunk/solr/webapp/web/js/scripts/app.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/scripts/app.js?rev=1292908&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/scripts/app.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/scripts/app.js Thu Feb 23 19:23:10 2012
@@ -0,0 +1,263 @@
+var loader = {
+    
+    show : function( element )
+    {
+        $( element )
+            .addClass( 'loader' );
+    },
+    
+    hide : function( element )
+    {
+        $( element )
+            .removeClass( 'loader' );
+    }
+    
+};
+
+Number.prototype.esc = function()
+{
+    return new String( this ).esc();
+}
+
+String.prototype.esc = function()
+{
+    return this.replace( /</g, '&lt;' ).replace( />/g, '&gt;' );
+}
+
+var sammy = $.sammy
+(
+    function()
+    {
+        this.bind
+        (
+            'run',
+            function( event, config )
+            {
+                if( 0 === config.start_url.length )
+                {
+                    location.href = '#/';
+                    return false;
+                }
+            }
+        );
+        
+        // activate_core
+        this.before
+        (
+            {},
+            function( context )
+            {
+                $( 'li[id].active', app.menu_element )
+                    .removeClass( 'active' );
+                
+                $( 'ul li.active', app.menu_element )
+                    .removeClass( 'active' );
+
+                if( this.params.splat )
+                {
+                    var active_element = $( '#' + this.params.splat[0], app.menu_element );
+                    
+                    if( 0 === active_element.size() )
+                    {
+                        var first_core = $( 'li[data-basepath]', app.menu_element ).attr( 'id' );
+                        var first_core_url = context.path.replace( new RegExp( '/' + this.params.splat[0] + '/' ), '/' + first_core + '/' );
+
+                        context.redirect( first_core_url );
+                        return false;
+                    }
+
+                    active_element
+                        .addClass( 'active' );
+
+                    if( this.params.splat[1] )
+                    {
+                        $( '.' + this.params.splat[1], active_element )
+                            .addClass( 'active' );
+                    }
+
+                    if( !active_element.hasClass( 'global' ) )
+                    {
+                        this.active_core = active_element;
+                    }
+                }
+            }
+        );
+    }
+);
+
+var solr_admin = function( app_config )
+{
+	self = this,
+
+    menu_element = null,
+
+    is_multicore = null,
+    cores_data = null,
+    active_core = null,
+    environment_basepath = null,
+    
+    config = app_config,
+    params = null,
+    dashboard_values = null,
+    schema_browser_data = null,
+
+    plugin_data = null,
+    
+    this.menu_element = $( '#menu ul' );
+    this.config = config;
+
+    this.run = function()
+    {
+        $.ajax
+        (
+            {
+                url : config.solr_path + config.core_admin_path + '?wt=json',
+                dataType : 'json',
+                beforeSend : function( arr, form, options )
+                {               
+                    $( '#content' )
+                        .html( '<div id="index"><div class="loader">Loading ...</div></div>' );
+                },
+                success : function( response )
+                {
+                    self.cores_data = response.status;
+                    is_multicore = 'undefined' === typeof response.status[''];
+
+                    if( is_multicore )
+                    {
+                        self.menu_element
+                            .addClass( 'multicore' );
+
+                        $( '#cores', menu_element )
+                            .show();
+                    }
+                    else
+                    {
+                        self.menu_element
+                            .addClass( 'singlecore' );
+                    }
+
+                    for( var core_name in response.status )
+                    {
+                        var core_path = config.solr_path + '/' + core_name;
+
+                        if( !core_name )
+                        {
+                            core_name = 'singlecore';
+                            core_path = config.solr_path
+                        }
+
+                        if( !environment_basepath )
+                        {
+                            environment_basepath = core_path;
+                        }
+
+                        var core_tpl = '<li id="' + core_name + '" data-basepath="' + core_path + '">' + "\n"
+                                     + '    <p><a href="#/' + core_name + '">' + core_name + '</a></p>' + "\n"
+                                     + '    <ul>' + "\n"
+
+                                     + '        <li class="ping"><a rel="' + core_path + '/admin/ping"><span>Ping</span></a></li>' + "\n"
+                                     + '        <li class="query"><a href="#/' + core_name + '/query"><span>Query</span></a></li>' + "\n"
+                                     + '        <li class="schema"><a href="#/' + core_name + '/schema"><span>Schema</span></a></li>' + "\n"
+                                     + '        <li class="config"><a href="#/' + core_name + '/config"><span>Config</span></a></li>' + "\n"
+                                     + '        <li class="replication"><a href="#/' + core_name + '/replication"><span>Replication</span></a></li>' + "\n"
+                                     + '        <li class="analysis"><a href="#/' + core_name + '/analysis"><span>Analysis</span></a></li>' + "\n"
+                                     + '        <li class="schema-browser"><a href="#/' + core_name + '/schema-browser"><span>Schema Browser</span></a></li>' + "\n"
+                                     + '        <li class="plugins"><a href="#/' + core_name + '/plugins"><span>Plugins</span></a></li>' + "\n"
+                                     + '        <li class="dataimport"><a href="#/' + core_name + '/dataimport"><span>Dataimport</span></a></li>' + "\n"
+
+                                     + '    </ul>' + "\n"
+                                     + '</li>';
+
+                        self.menu_element
+                            .append( core_tpl );
+                    }
+
+                    $.ajax
+                    (
+                        {
+                            url : environment_basepath + '/admin/system?wt=json',
+                            dataType : 'json',
+                            beforeSend : function( arr, form, options )
+                            {
+                            },
+                            success : function( response )
+                            {
+                                self.dashboard_values = response;
+
+                                var environment_args = null;
+                                var cloud_args = null;
+
+                                if( response.jvm && response.jvm.jmx && response.jvm.jmx.commandLineArgs )
+                                {
+                                    var command_line_args = response.jvm.jmx.commandLineArgs.join( ' | ' );
+
+                                    environment_args = command_line_args
+                                                            .match( /-Dsolr.environment=((dev|test|prod)?[\w\d]*)/i );
+
+                                    cloud_args = command_line_args
+                                                            .match( /-Dzk/i );
+                                }
+
+                                // environment
+
+                                var environment_element = $( '#environment' );
+                                if( environment_args )
+                                {
+                                    environment_element
+                                        .show();
+
+                                    if( environment_args[1] )
+                                    {
+                                        environment_element
+                                            .html( environment_args[1] );
+                                    }
+
+                                    if( environment_args[2] )
+                                    {
+                                        environment_element
+                                            .addClass( environment_args[2] );
+                                    }
+                                }
+                                else
+                                {
+                                    environment_element
+                                        .remove();
+                                }
+
+                                // cloud
+
+                                var cloud_nav_element = $( '#menu #cloud' );
+                                if( cloud_args )
+                                {
+                                    cloud_nav_element
+                                        .show();
+                                }
+
+                                // sammy
+
+                                sammy.run( location.hash );
+                            },
+                            error : function()
+                            {
+                            },
+                            complete : function()
+                            {
+                                loader.hide( this );
+                            }
+                        }
+                    );
+                },
+                error : function()
+                {
+                },
+                complete : function()
+                {
+                }
+            }
+        );
+    }
+
+};
+
+var app = new solr_admin( app_config );
\ No newline at end of file

Added: lucene/dev/trunk/solr/webapp/web/js/scripts/cloud.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/scripts/cloud.js?rev=1292908&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/scripts/cloud.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/scripts/cloud.js Thu Feb 23 19:23:10 2012
@@ -0,0 +1,174 @@
+// #/cloud
+sammy.get
+(
+    /^#\/(cloud)$/,
+    function( context )
+    {
+        var content_element = $( '#content' );
+
+        $.get
+        (
+            'tpl/cloud.html',
+            function( template )
+            {
+                content_element
+                    .html( template );
+
+                var cloud_element = $( '#cloud', content_element );
+                var cloud_content = $( '.content', cloud_element );
+
+                $.ajax
+                (
+                    {
+                        url : app.config.zookeeper_path,
+                        dataType : 'json',
+                        context : cloud_content,
+                        beforeSend : function( xhr, settings )
+                        {
+                            //this
+                            //    .html( '<div class="loader">Loading ...</div>' );
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            var self = this;
+                            
+                            $( '#tree', this )
+                                .jstree
+                                (
+                                    {
+                                        "plugins" : [ "json_data" ],
+                                        "json_data" : {
+                                            "data" : response.tree,
+                                            "progressive_render" : true
+                                        },
+                                        "core" : {
+                                            "animation" : 0
+                                        }
+                                    }
+                                );
+
+                            var tree_links = $( '#tree a', this );
+
+                            tree_links
+                                .die( 'click' )
+                                .live
+                                (
+                                    'click',
+                                    function( event )
+                                    {
+                                        $( 'a.active', $( this ).parents( '#tree' ) )
+                                            .removeClass( 'active' );
+                                        
+                                        $( this )
+                                            .addClass( 'active' );
+
+                                        cloud_content
+                                            .addClass( 'show' );
+
+                                        var file_content = $( '#file-content' );
+
+                                        $( 'a.close', file_content )
+                                            .die( 'click' )
+                                            .live
+                                            (
+                                                'click',
+                                                function( event )
+                                                {
+                                                    $( '#tree a.active' )
+                                                        .removeClass( 'active' );
+                                            
+                                                    cloud_content
+                                                        .removeClass( 'show' );
+
+                                                    return false;
+                                                }
+                                            );
+
+                                        $.ajax
+                                        (
+                                            {
+                                                url : this.href,
+                                                dataType : 'json',
+                                                context : file_content,
+                                                beforeSend : function( xhr, settings )
+                                                {
+                                                    //this
+                                                    //    .html( 'loading' )
+                                                    //    .show();
+                                                },
+                                                success : function( response, text_status, xhr )
+                                                {
+                                                    //this
+                                                    //    .html( '<pre>' + response.znode.data + '</pre>' );
+
+                                                    var props = [];
+                                                    for( var key in response.znode.prop )
+                                                    {
+                                                        props.push
+                                                        (
+                                                            '<li><dl class="clearfix">' + "\n" +
+                                                                '<dt>' + key.esc() + '</dt>' + "\n" +
+                                                                '<dd>' + response.znode.prop[key].esc() + '</dd>' + "\n" +
+                                                            '</dl></li>'
+                                                        );
+                                                    }
+
+                                                    $( '#prop ul', this )
+                                                        .empty()
+                                                        .html( props.join( "\n" ) );
+
+                                                    $( '#prop ul li:odd', this )
+                                                        .addClass( 'odd' );
+
+                                                    var data_element = $( '#data', this );
+
+                                                    if( 0 !== parseInt( response.znode.prop.children_count ) )
+                                                    {
+                                                        data_element.hide();
+                                                    }
+                                                    else
+                                                    {
+                                                        var data = response.znode.data
+                                                                 ? '<pre>' + response.znode.data.esc() + '</pre>'
+                                                                 : '<em>File "' + response.znode.path + '" has no Content</em>';
+
+                                                        data_element
+                                                            .show()
+                                                            .html( data );
+                                                    }
+                                                },
+                                                error : function( xhr, text_status, error_thrown)
+                                                {
+                                                },
+                                                complete : function( xhr, text_status )
+                                                {
+                                                }
+                                            }
+                                        );
+
+                                        return false;
+                                    }
+                                );
+                        },
+                        error : function( xhr, text_status, error_thrown )
+                        {
+                            var message = 'Loading of <code>' + app.config.zookeeper_path + '</code> failed with "' + text_status + '" '
+                                        + '(<code>' + error_thrown.message + '</code>)';
+
+                            if( 200 !== xhr.status )
+                            {
+                                message = 'Loading of <code>' + app.config.zookeeper_path + '</code> failed with HTTP-Status ' + xhr.status + ' ';
+                            }
+
+                            this
+                                .html( '<div class="block" id="error">' + message + '</div>' );
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                        }
+                    }
+                );
+            }
+        );
+    }
+);
\ No newline at end of file

Added: lucene/dev/trunk/solr/webapp/web/js/scripts/cores.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/scripts/cores.js?rev=1292908&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/scripts/cores.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/scripts/cores.js Thu Feb 23 19:23:10 2012
@@ -0,0 +1,495 @@
+sammy.bind
+(
+    'cores_load_data',
+    function( event, params )
+    {
+        if( app.cores_data )
+        {
+            params.callback( app.cores_data );
+            return true;
+        }
+
+        $.ajax
+        (
+            {
+                url : app.config.solr_path + app.config.core_admin_path + '?wt=json',
+                dataType : 'json',
+                beforeSend : function( xhr, settings )
+                {
+                },
+                success : function( response, text_status, xhr )
+                {
+                    app.cores_data = response.status;
+                    params.callback( app.cores_data );
+                },
+                error : function( xhr, text_status, error_thrown)
+                {
+                },
+                complete : function( xhr, text_status )
+                {
+                }
+            }
+        );
+    }
+);
+
+sammy.bind
+(
+    'cores_build_navigation',
+    function( event, params )
+    {
+        var navigation_content = ['<ul>'];
+
+        for( var core in params.cores )
+        {
+            navigation_content.push( '<li><a href="' + params.basepath + core + '">' + core + '</a></li>' );
+        }
+
+        params.navigation_element
+            .html( navigation_content.join( "\n" ) );
+        
+        $( 'a[href="' + params.basepath + params.current_core + '"]', params.navigation_element ).parent()
+            .addClass( 'current' );
+    }
+);
+
+sammy.bind
+(
+    'cores_load_template',
+    function( event, params )
+    {
+        if( app.cores_template )
+        {
+            params.callback();
+            return true;
+        }
+
+        $.get
+        (
+            'tpl/cores.html',
+            function( template )
+            {
+                params.content_element
+                    .html( template );
+             
+                app.cores_template = template;   
+                params.callback();
+            }
+        );
+    }
+);
+
+// #/cores
+sammy.get
+(
+    /^#\/(cores)$/,
+    function( context )
+    {
+        delete app.cores_template;
+
+        sammy.trigger
+        (
+            'cores_load_data',
+            {
+                callback :  function( cores )
+                {
+                    var first_core = null;
+                    for( var key in cores )
+                    {
+                        if( !first_core )
+                        {
+                            first_core = key;
+                        }
+                        continue;
+                    }
+                    context.redirect( context.path + '/' + first_core );
+                }
+            }
+        );
+    }
+);
+
+// #/cores
+sammy.get
+(
+    /^#\/(cores)\//,
+    function( context )
+    {
+        var content_element = $( '#content' );
+
+        var path_parts = this.path.match( /^(.+\/cores\/)(.*)$/ );
+        var current_core = path_parts[2];
+
+        sammy.trigger
+        (
+            'cores_load_data',
+            {
+                callback : function( cores )
+                {
+                    sammy.trigger
+                    (
+                        'cores_load_template',
+                        {
+                            content_element : content_element,
+                            callback : function()
+                            {
+                                var cores_element = $( '#cores', content_element );
+                                var navigation_element = $( '#navigation', cores_element );
+                                var list_element = $( '#list', navigation_element );
+                                var data_element = $( '#data', cores_element );
+                                var core_data_element = $( '#core-data', data_element );
+                                var index_data_element = $( '#index-data', data_element );
+
+                                sammy.trigger
+                                (
+                                    'cores_build_navigation',
+                                    {
+                                        cores : cores,
+                                        basepath : path_parts[1],
+                                        current_core : current_core,
+                                        navigation_element : list_element
+                                    }
+                                );
+
+                                var core_data = cores[current_core];
+                                var core_basepath = $( '#' + current_core, app.menu_element ).attr( 'data-basepath' );
+
+                                // core-data
+
+                                $( 'h2 span', core_data_element )
+                                    .html( core_data.name );
+
+                                $( '.startTime dd', core_data_element )
+                                    .html( core_data.startTime );
+
+                                $( '.instanceDir dd', core_data_element )
+                                    .html( core_data.instanceDir );
+
+                                $( '.dataDir dd', core_data_element )
+                                    .html( core_data.dataDir );
+
+                                // index-data
+
+                                $( '.lastModified dd', index_data_element )
+                                    .html( core_data.index.lastModified );
+
+                                $( '.version dd', index_data_element )
+                                    .html( core_data.index.version );
+
+                                $( '.numDocs dd', index_data_element )
+                                    .html( core_data.index.numDocs );
+
+                                $( '.maxDoc dd', index_data_element )
+                                    .html( core_data.index.maxDoc );
+
+                                $( '.optimized dd', index_data_element )
+                                    .addClass( core_data.index.optimized ? 'ico-1' : 'ico-0' );
+
+                                $( '#actions .optimize', cores_element )
+                                    .show();
+
+                                $( '.optimized dd span', index_data_element )
+                                    .html( core_data.index.optimized ? 'yes' : 'no' );
+
+                                $( '.current dd', index_data_element )
+                                    .addClass( core_data.index.current ? 'ico-1' : 'ico-0' );
+
+                                $( '.current dd span', index_data_element )
+                                    .html( core_data.index.current ? 'yes' : 'no' );
+
+                                $( '.hasDeletions dd', index_data_element )
+                                    .addClass( core_data.index.hasDeletions ? 'ico-1' : 'ico-0' );
+
+                                $( '.hasDeletions dd span', index_data_element )
+                                    .html( core_data.index.hasDeletions ? 'yes' : 'no' );
+
+                                $( '.directory dd', index_data_element )
+                                    .html
+                                    (
+                                        core_data.index.directory
+                                            .replace( /:/g, ':&#8203;' )
+                                            .replace( /@/g, '@&#8203;' )
+                                    );
+
+                                var core_names = [];
+                                var core_selects = $( '#actions select', cores_element );
+
+                                for( var key in cores )
+                                {
+                                    core_names.push( '<option value="' + key + '">' + key + '</option>' )
+                                }
+
+                                core_selects
+                                    .html( core_names.join( "\n") );
+                                
+                                $( 'option[value="' + current_core + '"]', core_selects.filter( '#swap_core' ) )
+                                    .attr( 'selected', 'selected' );
+
+                                $( 'option[value="' + current_core + '"]', core_selects.filter( '.other' ) )
+                                    .attr( 'disabled', 'disabled' )
+                                    .addClass( 'disabled' );
+                                
+                                $( 'input[name="core"]', cores_element )
+                                    .val( current_core );
+
+                                // layout
+
+                                var actions_element = $( '.actions', cores_element );
+                                var button_holder_element = $( '.button-holder.options', actions_element );
+
+                                button_holder_element
+                                    .die( 'toggle' )
+                                    .live
+                                    (
+                                        'toggle',
+                                        function( event )
+                                        {
+                                            var element = $( this );
+                                        
+                                            element
+                                                .toggleClass( 'active' );
+                                            
+                                            if( element.hasClass( 'active' ) )
+                                            {
+                                                button_holder_element
+                                                    .not( element )
+                                                    .removeClass( 'active' );
+                                            }
+                                        }
+                                    );
+
+                                $( '.button a', button_holder_element )
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            $( this ).parents( '.button-holder' )
+                                                .trigger( 'toggle' );
+                                        }
+                                    );
+
+                                $( 'form a.submit', button_holder_element )
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            var element = $( this );
+                                            var form_element = element.parents( 'form' );
+                                            var action = $( 'input[name="action"]', form_element ).val().toLowerCase();
+
+                                            form_element
+                                                .ajaxSubmit
+                                                (
+                                                    {
+                                                        url : app.config.solr_path + app.config.core_admin_path + '?wt=json',
+                                                        dataType : 'json',
+                                                        beforeSubmit : function( array, form, options )
+                                                        {
+                                                            //loader
+                                                        },
+                                                        success : function( response, status_text, xhr, form )
+                                                        {
+                                                            delete app.cores_data;
+
+                                                            if( 'rename' === action )
+                                                            {
+                                                                context.redirect( path_parts[1] + $( 'input[name="other"]', form_element ).val() );
+                                                            }
+                                                            else if( 'swap' === action )
+                                                            {
+                                                                window.location.reload();
+                                                            }
+                                                            
+                                                            $( 'a.reset', form )
+                                                                .trigger( 'click' );
+                                                        },
+                                                        error : function( xhr, text_status, error_thrown )
+                                                        {
+                                                        },
+                                                        complete : function()
+                                                        {
+                                                            //loader
+                                                        }
+                                                    }
+                                                );
+
+                                            return false;
+                                        }
+                                    );
+
+                                $( 'form a.reset', button_holder_element )
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            $( this ).parents( 'form' )
+                                                .resetForm();
+
+                                            $( this ).parents( '.button-holder' )
+                                                .trigger( 'toggle' );
+                                            
+                                            return false;
+                                        }
+                                    );
+
+                                var reload_button = $( '#actions .reload', cores_element );
+                                reload_button
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            $.ajax
+                                            (
+                                                {
+                                                    url : app.config.solr_path + app.config.core_admin_path + '?wt=json&action=RELOAD&core=' + current_core,
+                                                    dataType : 'json',
+                                                    context : $( this ),
+                                                    beforeSend : function( xhr, settings )
+                                                    {
+                                                        this
+                                                            .addClass( 'loader' );
+                                                    },
+                                                    success : function( response, text_status, xhr )
+                                                    {
+                                                        this
+                                                            .addClass( 'success' );
+
+                                                        window.setTimeout
+                                                        (
+                                                            function()
+                                                            {
+                                                                reload_button
+                                                                    .removeClass( 'success' );
+                                                            },
+                                                            5000
+                                                        );
+                                                    },
+                                                    error : function( xhr, text_status, error_thrown )
+                                                    {
+                                                    },
+                                                    complete : function( xhr, text_status )
+                                                    {
+                                                        this
+                                                            .removeClass( 'loader' );
+                                                    }
+                                                }
+                                            );
+                                        }
+                                    );
+                                
+                                $( '#actions .unload', cores_element )
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            $.ajax
+                                            (
+                                                {
+                                                    url : app.config.solr_path + app.config.core_admin_path + '?wt=json&action=UNLOAD&core=' + current_core,
+                                                    dataType : 'json',
+                                                    context : $( this ),
+                                                    beforeSend : function( xhr, settings )
+                                                    {
+                                                        this
+                                                            .addClass( 'loader' );
+                                                    },
+                                                    success : function( response, text_status, xhr )
+                                                    {
+                                                        delete app.cores_data;
+                                                        context.redirect( path_parts[1].substr( 0, path_parts[1].length - 1 ) );
+                                                    },
+                                                    error : function( xhr, text_status, error_thrown )
+                                                    {
+                                                    },
+                                                    complete : function( xhr, text_status )
+                                                    {
+                                                        this
+                                                            .removeClass( 'loader' );
+                                                    }
+                                                }
+                                            );
+                                        }
+                                    );
+
+                                var optimize_button = $( '#actions .optimize', cores_element );
+                                optimize_button
+                                    .die( 'click' )
+                                    .live
+                                    (
+                                        'click',
+                                        function( event )
+                                        {
+                                            $.ajax
+                                            (
+                                                {
+                                                    url : core_basepath + '/update?optimize=true&waitFlush=true&wt=json',
+                                                    dataType : 'json',
+                                                    context : $( this ),
+                                                    beforeSend : function( xhr, settings )
+                                                    {
+                                                        this
+                                                            .addClass( 'loader' );
+                                                    },
+                                                    success : function( response, text_status, xhr )
+                                                    {
+                                                        this
+                                                            .addClass( 'success' );
+
+                                                        window.setTimeout
+                                                        (
+                                                            function()
+                                                            {
+                                                                optimize_button
+                                                                    .removeClass( 'success' );
+                                                            },
+                                                            5000
+                                                        );
+                                                        
+                                                        $( '.optimized dd.ico-0', index_data_element )
+                                                            .removeClass( 'ico-0' )
+                                                            .addClass( 'ico-1' );
+                                                    },
+                                                    error : function( xhr, text_status, error_thrown)
+                                                    {
+                                                        console.warn( 'd0h, optimize broken!' );
+                                                    },
+                                                    complete : function( xhr, text_status )
+                                                    {
+                                                        this
+                                                            .removeClass( 'loader' );
+                                                    }
+                                                }
+                                            );
+                                        }
+                                    );
+
+                                $( '.timeago', data_element )
+                                     .timeago();
+
+                                $( 'ul', data_element )
+                                    .each
+                                    (
+                                        function( i, element )
+                                        {
+                                            $( 'li:odd', element )
+                                                .addClass( 'odd' );
+                                        }
+                                    )
+                            }
+                        }
+                    );
+                }
+            }
+        );
+    }
+);
\ No newline at end of file

Added: lucene/dev/trunk/solr/webapp/web/js/scripts/dashboard.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/scripts/dashboard.js?rev=1292908&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/scripts/dashboard.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/scripts/dashboard.js Thu Feb 23 19:23:10 2012
@@ -0,0 +1,400 @@
+// #/:core
+sammy.get
+(
+    /^#\/([\w\d-]+)$/,
+    function( context )
+    {
+        var core_basepath = this.active_core.attr( 'data-basepath' );
+        var content_element = $( '#content' );
+        
+        content_element
+            .removeClass( 'single' );
+        
+        var core_menu = $( 'ul', this.active_core );
+        if( !core_menu.data( 'admin-extra-loaded' ) )
+        {
+            core_menu.data( 'admin-extra-loaded', new Date() );
+
+            $.get
+            (
+                core_basepath + '/admin/file/?file=admin-extra.menu-top.html',
+                function( menu_extra )
+                {
+                    core_menu
+                        .prepend( menu_extra );
+                }
+            );
+            
+            $.get
+            (
+                core_basepath + '/admin/file/?file=admin-extra.menu-bottom.html',
+                function( menu_extra )
+                {
+                    core_menu
+                        .append( menu_extra );
+                }
+            );
+        }
+        
+        $.get
+        (
+            'tpl/dashboard.html',
+            function( template )
+            {
+                content_element
+                    .html( template );
+                    
+                var dashboard_element = $( '#dashboard' );
+                                     
+                $.ajax
+                (
+                    {
+                        url : core_basepath + '/admin/luke?wt=json&show=index&numTerms=0',
+                        dataType : 'json',
+                        context : $( '#statistics', dashboard_element ),
+                        beforeSend : function( xhr, settings )
+                        {
+                            $( 'h2', this )
+                                .addClass( 'loader' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Loading ...' );
+                            
+                            $( '.content' )
+                                .hide();
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            $( '.message', this )
+                                .empty()
+                                .hide();
+                            
+                            $( '.content', this )
+                                .show();
+                                
+                            var data = {
+                                'index_num-docs' : response['index']['numDocs'],
+                                'index_max-doc' : response['index']['maxDoc'],
+                                'index_version' : response['index']['version'],
+                                'index_segmentCount' : response['index']['segmentCount'],
+                                'index_last-modified' : response['index']['lastModified']
+                            };
+                            
+                            for( var key in data )
+                            {
+                                $( '.' + key, this )
+                                    .show();
+                                
+                                $( '.value.' + key, this )
+                                    .html( data[key] );
+                            }
+
+                            var optimized_element = $( '.value.index_optimized', this );
+                            if( !response['index']['hasDeletions'] )
+                            {
+                                optimized_element
+                                    .addClass( 'ico-1' );
+
+                                $( 'span', optimized_element )
+                                    .html( 'yes' );
+                            }
+                            else
+                            {
+                                optimized_element
+                                    .addClass( 'ico-0' );
+
+                                $( 'span', optimized_element )
+                                    .html( 'no' );
+                            }
+
+                            var current_element = $( '.value.index_current', this );
+                            if( response['index']['current'] )
+                            {
+                                current_element
+                                    .addClass( 'ico-1' );
+
+                                $( 'span', current_element )
+                                    .html( 'yes' );
+                            }
+                            else
+                            {
+                                current_element
+                                    .addClass( 'ico-0' );
+
+                                $( 'span', current_element )
+                                    .html( 'no' );
+                            }
+
+                            $( 'a', optimized_element )
+                                .die( 'click' )
+                                .live
+                                (
+                                    'click',
+                                    function( event )
+                                    {                        
+                                        $.ajax
+                                        (
+                                            {
+                                                url : core_basepath + '/update?optimize=true&waitFlush=true&wt=json',
+                                                dataType : 'json',
+                                                context : $( this ),
+                                                beforeSend : function( xhr, settings )
+                                                {
+                                                    this
+                                                        .addClass( 'loader' );
+                                                },
+                                                success : function( response, text_status, xhr )
+                                                {
+                                                    this.parents( 'dd' )
+                                                        .removeClass( 'ico-0' )
+                                                        .addClass( 'ico-1' );
+                                                },
+                                                error : function( xhr, text_status, error_thrown)
+                                                {
+                                                    console.warn( 'd0h, optimize broken!' );
+                                                },
+                                                complete : function( xhr, text_status )
+                                                {
+                                                    this
+                                                        .removeClass( 'loader' );
+                                                }
+                                            }
+                                        );
+                                    }
+                                );
+
+                            $( '.timeago', this )
+                                 .timeago();
+                        },
+                        error : function( xhr, text_status, error_thrown )
+                        {
+                            this
+                                .addClass( 'disabled' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Luke is not configured' );
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                            $( 'h2', this )
+                                .removeClass( 'loader' );
+                        }
+                    }
+                );
+                
+                $.ajax
+                (
+                    {
+                        url : core_basepath + '/replication?command=details&wt=json',
+                        dataType : 'json',
+                        context : $( '#replication', dashboard_element ),
+                        beforeSend : function( xhr, settings )
+                        {
+                            $( 'h2', this )
+                                .addClass( 'loader' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Loading' );
+
+                            $( '.content', this )
+                                .hide();
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            $( '.message', this )
+                                .empty()
+                                .hide();
+
+                            $( '.content', this )
+                                .show();
+                            
+                            $( '.replication', context.active_core )
+                                .show();
+                            
+                            var data = response.details;
+                            var is_slave = 'undefined' !== typeof( data.slave );
+                            var headline = $( 'h2 span', this );
+                            var details_element = $( '#details', this );
+                            var current_type_element = $( ( is_slave ? '.slave' : '.master' ), this );
+
+                            if( is_slave )
+                            {
+                                this
+                                    .addClass( 'slave' );
+                                
+                                headline
+                                    .html( headline.html() + ' (Slave)' );
+                            }
+                            else
+                            {
+                                this
+                                    .addClass( 'master' );
+                                
+                                headline
+                                    .html( headline.html() + ' (Master)' );
+                            }
+
+                            $( '.version div', current_type_element )
+                                .html( data.indexVersion );
+                            $( '.generation div', current_type_element )
+                                .html( data.generation );
+                            $( '.size div', current_type_element )
+                                .html( data.indexSize );
+                            
+                            if( is_slave )
+                            {
+                                var master_element = $( '.master', details_element );
+                                $( '.version div', master_element )
+                                    .html( data.slave.masterDetails.indexVersion );
+                                $( '.generation div', master_element )
+                                    .html( data.slave.masterDetails.generation );
+                                $( '.size div', master_element )
+                                    .html( data.slave.masterDetails.indexSize );
+                                
+                                if( data.indexVersion !== data.slave.masterDetails.indexVersion )
+                                {
+                                    $( '.version', details_element )
+                                        .addClass( 'diff' );
+                                }
+                                else
+                                {
+                                    $( '.version', details_element )
+                                        .removeClass( 'diff' );
+                                }
+                                
+                                if( data.generation !== data.slave.masterDetails.generation )
+                                {
+                                    $( '.generation', details_element )
+                                        .addClass( 'diff' );
+                                }
+                                else
+                                {
+                                    $( '.generation', details_element )
+                                        .removeClass( 'diff' );
+                                }
+                            }
+                        },
+                        error : function( xhr, text_status, error_thrown)
+                        {
+                            this
+                                .addClass( 'disabled' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Replication is not configured' );
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                            $( 'h2', this )
+                                .removeClass( 'loader' );
+                        }
+                    }
+                );
+
+                $.ajax
+                (
+                    {
+                        url : core_basepath + '/dataimport?command=details&wt=json',
+                        dataType : 'json',
+                        context : $( '#dataimport', dashboard_element ),
+                        beforeSend : function( xhr, settings )
+                        {
+                            $( 'h2', this )
+                                .addClass( 'loader' );
+
+                            $( '.message', this )
+                                .show()
+                                .html( 'Loading' );
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            $( '.message', this )
+                                .empty()
+                                .hide();
+                            
+                            $( 'dl', this )
+                                .show();
+                            
+                            var data = {
+                                'status' : response['status'],
+                                'info' : response['statusMessages']['']
+                            };
+                            
+                            for( var key in data )
+                            {
+                                $( '.' + key, this )
+                                    .show();
+                                
+                                $( '.value.' + key, this )
+                                    .html( data[key] );
+                            }
+                        },
+                        error : function( xhr, text_status, error_thrown)
+                        {
+                            this
+                                .addClass( 'disabled' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Dataimport is not configured' );
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                            $( 'h2', this )
+                                .removeClass( 'loader' );
+                        }
+                    }
+                );
+                
+                $.ajax
+                (
+                    {
+                        url : core_basepath + '/admin/file/?file=admin-extra.html',
+                        dataType : 'html',
+                        context : $( '#admin-extra', dashboard_element ),
+                        beforeSend : function( xhr, settings )
+                        {
+                            $( 'h2', this )
+                                .addClass( 'loader' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'Loading' );
+
+                            $( '.content', this )
+                                .hide();
+                        },
+                        success : function( response, text_status, xhr )
+                        {
+                            $( '.message', this )
+                                .hide()
+                                .empty();
+
+                            $( '.content', this )
+                                .show()
+                                .html( response );
+                        },
+                        error : function( xhr, text_status, error_thrown)
+                        {
+                            this
+                                .addClass( 'disabled' );
+                            
+                            $( '.message', this )
+                                .show()
+                                .html( 'We found no "admin-extra.html" file.' );
+                        },
+                        complete : function( xhr, text_status )
+                        {
+                            $( 'h2', this )
+                                .removeClass( 'loader' );
+                        }
+                    }
+                );
+                
+            }
+        );
+    }
+);
\ No newline at end of file