Index: trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/js/rosetta-roles.js
===================================================================
--- trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/js/rosetta-roles.js	(revision 2539)
+++ trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/js/rosetta-roles.js	(working copy)
@@ -21,10 +21,12 @@
 		},
 
 		initialize: function() {
-			var subProjects = this.get( 'sub_projects' );
+			this.baseCollection = this.get( 'sub_projects' );
 			this.unset( 'sub_projects' );
 
-			this.set( 'subProjects', new projects.model.subProjects( subProjects ) );
+			this.set( 'subProjects', new projects.model.subProjects( this.baseCollection, {
+				project: this,
+			} ) );
 			this.set( 'checked', _.contains( projects.settings.accessList, parseInt( this.get( 'id' ), 10 ) ) );
 
 			this.listenTo( this.get( 'subProjects' ), 'change:checked', this.updateChecked );
@@ -83,8 +85,7 @@
 		defaults: {
 			id: 0,
 			name: '',
-			checked: false,
-			isVisible: true
+			checked: false
 		},
 
 		initialize: function() {
@@ -98,7 +99,8 @@
 		// Search terms
 		terms: '',
 
-		initialize: function() {
+		initialize: function( models, options ) {
+			this.project = options.project;
 			this.on( 'uncheckall', this.uncheckall );
 		},
 
@@ -120,18 +122,23 @@
 				this.search( this.terms );
 			}
 
-			if ( this.terms === '' ) {
-				this.each( function( project ) {
-					project.set( 'isVisible', true );
-				});
+			// If search is blank, show all projects.
+			if ( '' === this.terms ) {
+				this.reset( this.project.baseCollection );
 			}
+
+			// Trigger a 'projects:update' event
+			this.trigger( 'projects:update' );
 		},
 
 		// Performs a search within the collection
 		// @uses RegExp
 		search: function( term ) {
-			var match;
+			var match, results;
 
+			// Start with a full collection
+			this.reset( this.project.baseCollection, { silent: true } );
+
 			// Escape the term string for RegExp meta characters
 			term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' );
 
@@ -140,11 +147,12 @@
 			term = term.replace( / /g, ')(?=.*' );
 			match = new RegExp( '^(?=.*' + term + ').+', 'i' );
 
-			// Find results
-			this.each( function( project ) {
+			results = this.filter( function( project ) {
 				var haystack = _.union( [ project.get( 'name' ), project.get( 'slug' ) ] );
-				project.set( 'isVisible', match.test( haystack ) );
+				return match.test( haystack );
 			});
+
+			this.reset( results );
 		},
 
 		comparator: function( project ) {
@@ -262,19 +270,38 @@
 			this.views.add( new projects.view.SubProjectsList({
 				collection: collection
 			}) );
-		}
+		},
+
 	});
 
 	projects.view.SubProjectsList = wp.Backbone.View.extend({
 		tagName: 'ul',
 		className: 'sub-projects-list',
 
-		initialize: function() {
-			var view = this;
-			this.collection.each( function( project ) {
-				view.views.add( new projects.view.SubProject({
-					model: project
-				}) );
+		// How many projects should be rendered.
+		limit: 100,
+
+		initialize: function( options ) {
+			var self = this;
+
+			this.listenTo( self.collection, 'projects:update', function() {
+				self.render( this );
+			} );
+		},
+
+		render: function() {
+			var self = this, subProjects;
+
+			self.$el.empty();
+
+			subProjects = self.collection.first( self.limit );
+			_.each( subProjects, function( model ) {
+				var subProjectView = new projects.view.SubProject({
+					model: model
+				});
+
+				subProjectView.render();
+				self.$el.append( subProjectView.el );
 			});
 		}
 	});
@@ -286,16 +313,6 @@
 			this.views.add( new projects.view.Checkbox({
 				model: this.model
 			}) );
-
-			this.listenTo( this.model, 'change:isVisible', this.changeVisibility );
-		},
-
-		changeVisibility: function() {
-			if ( this.model.get( 'isVisible' ) ) {
-				this.$el.removeClass( 'hidden' );
-			} else {
-				this.$el.addClass( 'hidden' );
-			}
 		}
 	});
 
@@ -332,15 +349,30 @@
 
 		doSearch: _.debounce( function( event ) {
 			this.collection.doSearch( event.target.value );
-		}, 200 )
+		}, 500 )
 	});
 
-	projects.init = function() {
+	projects.initFrame = function( projectData ) {
 		projects.view.frame = new projects.view.Frame({
-			collection: new projects.model.Projects( projects.settings.data )
+			collection: new projects.model.Projects( projectData )
 		}).render();
 	};
 
+	projects.init = function() {
+		var projectData = localStorage.getItem( 'projectData' );
+		if ( projectData ) {
+			projectData = JSON.parse( projectData );
+			projects.initFrame( projectData );
+			return;
+		}
+
+		wp.ajax.post( 'rosetta-get-project-data' )
+			.done( function( projectData ) {
+				var r = localStorage.setItem( 'projectData', JSON.stringify( projectData ) );
+				projects.initFrame( projectData );
+			} );
+	};
+
 	$( projects.init );
 
 	$( '#project-all' ).on( 'click', function() {
Index: trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php
===================================================================
--- trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php	(revision 2539)
+++ trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php	(working copy)
@@ -76,6 +76,8 @@
 
 		add_action( 'translation_editor_added', array( $this, 'update_wporg_profile_badge' ) );
 		add_action( 'translation_editor_removed', array( $this, 'update_wporg_profile_badge' ) );
+
+		add_action( 'wp_ajax_rosetta-get-project-data', array( $this, 'ajax_get_project_data' ) );
 	}
 
 	/**
@@ -618,6 +620,21 @@
 	 * Renders the edit page.
 	 */
 	private function render_edit_translation_editor( $user_id ) {
+		$project_access_list = $this->get_users_projects( $user_id );
+
+		wp_localize_script( 'rosetta-roles', '_rosettaProjectsSettings', array(
+			'l10n' => array(
+				'searchPlaceholder' => esc_attr__( 'Search...', 'rosetta' ),
+			),
+			'accessList' => $project_access_list,
+		) );
+
+		$feedback_message = $this->get_feedback_message();
+
+		require __DIR__ . '/views/edit-translation-editor.php';
+	}
+
+	public function ajax_get_project_data() {
 		$projects = $this->get_translate_projects();
 		$project_tree = $this->get_project_tree( $projects, 0, 1 );
 
@@ -631,19 +648,7 @@
 		}
 		$project_tree = array_values( $project_tree );
 
-		$project_access_list = $this->get_users_projects( $user_id );
-
-		wp_localize_script( 'rosetta-roles', '_rosettaProjectsSettings', array(
-			'l10n' => array(
-				'searchPlaceholder' => esc_attr__( 'Search...', 'rosetta' ),
-			),
-			'data' => $project_tree,
-			'accessList' => $project_access_list,
-		) );
-
-		$feedback_message = $this->get_feedback_message();
-
-		require __DIR__ . '/views/edit-translation-editor.php';
+		wp_send_json_success( $project_tree );
 	}
 
 	/**
