diff --git a/app/assets/javascripts/app/app.js b/app/assets/javascripts/app/app.js
index 4d42b6b0cdfe80bbe654f449c8eb1dbbfb26a2ca..4127b12252212e33ac79e6fd20450d71f3350f12 100644
--- a/app/assets/javascripts/app/app.js
+++ b/app/assets/javascripts/app/app.js
@@ -51,6 +51,7 @@ var app = {
     this.setupBackboneLinks();
     this.setupGlobalViews();
     this.setupDisabledLinks();
+    this.setupForms();
   },
 
   hasPreload : function(prop) {
@@ -136,6 +137,17 @@ var app = {
     $("a.disabled").click(function(event) {
       event.preventDefault();
     });
+  },
+
+  setupForms: function() {
+    // add placeholder support for old browsers
+    $("input, textarea").placeholder();
+
+    // setup remote forms
+    $(document).on("ajax:success", "form[data-remote]", function() {
+      $(this).clearForm();
+      $(this).focusout();
+    });
   }
 };
 
diff --git a/app/assets/javascripts/app/views.js b/app/assets/javascripts/app/views.js
index f92b043120ccb0e5514976f85e86227d22d48968..ae4d352824ef5b5175a5157b38cd6c37fa88d53e 100644
--- a/app/assets/javascripts/app/views.js
+++ b/app/assets/javascripts/app/views.js
@@ -50,6 +50,9 @@ app.views.Base = Backbone.View.extend({
     // add avatar fallback if it can't be loaded
     this.$el.find(this.avatars.selector).error(this.avatars.fallback);
 
+    // add placeholder support for old browsers
+    this.$("input, textarea").placeholder();
+
     this.postRenderTemplate();
   },
 
diff --git a/app/assets/javascripts/app/views/comment_stream_view.js b/app/assets/javascripts/app/views/comment_stream_view.js
index 07efa4f719dc7320381028057af6aa7f7f49a6f4..fe7c240e38fa25f74a4e2d9bd2eef8305af04306 100644
--- a/app/assets/javascripts/app/views/comment_stream_view.js
+++ b/app/assets/javascripts/app/views/comment_stream_view.js
@@ -26,7 +26,6 @@ app.views.CommentStream = app.views.Base.extend({
   },
 
   postRenderTemplate : function() {
-    this.$("textarea").placeholder();
     this.model.comments.each(this.appendComment, this);
 
     // add autoexpanders to new comment textarea
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index adc3bcc7a3026aa66160421f7cb1cdba5fbc5b11..ff8d9175022f972ead6794a604c7c1b8d6587c63 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -39,7 +39,6 @@
 //= require_tree ./helpers
 //= require_tree ./pages
 //= require_tree ./widgets
-//= require view
 //= require mentions
 //= require bootstrap
 //= require osmlocator
diff --git a/app/assets/javascripts/view.js b/app/assets/javascripts/view.js
deleted file mode 100644
index 7d20a491f5004deb910d9286bf9443066ebc2b6f..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/view.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
-var View = {
-  initialize: function() {
-    /* label placeholders */
-    $("input, textarea").placeholder();
-
-    $(document).on('ajax:success', 'form[data-remote]', function () {
-      $(this).clearForm();
-      $(this).focusout();
-    });
-
-    /* tag following */
-    $("#new_tag_following .tag_input").bind('focus', function(){
-      $(this).siblings("#tag_following_submit").removeClass('hidden');
-    });
-  },
-};
-
-$(function() {
-  View.initialize();
-});
-// @license-end
diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js
index 2840c1d318ca0744b23e82a537ae7bbca2b1d248..84f4a72f36ac17177d01984fdcdd621b452d56d3 100644
--- a/spec/javascripts/app/app_spec.js
+++ b/spec/javascripts/app/app_spec.js
@@ -1,4 +1,28 @@
 describe("app", function() {
+  describe("initialize", function() {
+    it("calls several setup functions", function() {
+      spyOn(app.Router.prototype, "initialize");
+      spyOn(app, "setupDummyPreloads");
+      spyOn(app, "setupUser");
+      spyOn(app, "setupHeader");
+      spyOn(app, "setupBackboneLinks");
+      spyOn(app, "setupGlobalViews");
+      spyOn(app, "setupDisabledLinks");
+      spyOn(app, "setupForms");
+
+      app.initialize();
+
+      expect(app.Router.prototype.initialize).toHaveBeenCalled();
+      expect(app.setupDummyPreloads).toHaveBeenCalled();
+      expect(app.setupUser).toHaveBeenCalled();
+      expect(app.setupHeader).toHaveBeenCalled();
+      expect(app.setupBackboneLinks).toHaveBeenCalled();
+      expect(app.setupGlobalViews).toHaveBeenCalled();
+      expect(app.setupDisabledLinks).toHaveBeenCalled();
+      expect(app.setupForms).toHaveBeenCalled();
+    });
+  });
+
   describe("user", function() {
     it("returns false if the current_user isn't set", function() {
       app._user = undefined;
@@ -11,4 +35,13 @@ describe("app", function() {
       expect(app.user().get("name")).toEqual("alice");
     });
   });
+
+  describe("setupForms", function() {
+    it("calls jQuery.placeholder() for inputs", function() {
+      spyOn($.fn, "placeholder");
+      app.setupForms();
+      expect($.fn.placeholder).toHaveBeenCalled();
+      expect($.fn.placeholder.calls.mostRecent().object.selector).toBe("input, textarea");
+    });
+  });
 });
diff --git a/spec/javascripts/app/views/comment_stream_view_spec.js b/spec/javascripts/app/views/comment_stream_view_spec.js
index 7578f7e5e3b03e5f956a5350b56bfd998f685e4f..0c27ecf0c9b6326dd3b4fb64bcfb6606496187a5 100644
--- a/spec/javascripts/app/views/comment_stream_view_spec.js
+++ b/spec/javascripts/app/views/comment_stream_view_spec.js
@@ -14,13 +14,6 @@ describe("app.views.CommentStream", function(){
   });
 
   describe("postRenderTemplate", function(){
-    it("applies infield labels", function(){
-      spyOn($.fn, "placeholder");
-      this.view.postRenderTemplate();
-      expect($.fn.placeholder).toHaveBeenCalled();
-      expect($.fn.placeholder.calls.mostRecent().object.selector).toBe("textarea");
-    });
-
     it("autoResizes the new comment textarea", function(){
       spyOn(window, "autosize");
       this.view.postRenderTemplate();
diff --git a/spec/javascripts/app/views_spec.js b/spec/javascripts/app/views_spec.js
index e33c0585ff9db38dace52e5dbff807a90cab7d21..1204ca4d189147321f75a0965b9f670bbf24aecc 100644
--- a/spec/javascripts/app/views_spec.js
+++ b/spec/javascripts/app/views_spec.js
@@ -69,7 +69,6 @@ describe("app.views.Base", function(){
         expect($.fn.timeago.calls.mostRecent().object.selector).toBe("time");
       });
 
-
       it("initializes tooltips declared with the view's tooltipSelector property", function(){
         this.view.tooltipSelector = ".christopher_columbus, .barrack_obama, .block_user";
 
@@ -77,6 +76,13 @@ describe("app.views.Base", function(){
         this.view.render();
         expect($.fn.tooltip.calls.mostRecent().object.selector).toBe(".christopher_columbus, .barrack_obama, .block_user");
       });
+
+      it("applies infield labels", function(){
+        spyOn($.fn, "placeholder");
+        this.view.render();
+        expect($.fn.placeholder).toHaveBeenCalled();
+        expect($.fn.placeholder.calls.mostRecent().object.selector).toBe("input, textarea");
+      });
     });
   });
 });
diff --git a/spec/javascripts/view-spec.js b/spec/javascripts/view-spec.js
deleted file mode 100644
index b9fba7ee97eb85ae5546c061b55678a496fa430e..0000000000000000000000000000000000000000
--- a/spec/javascripts/view-spec.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/*  Copyright (c) 2010-2011, Diaspora Inc.  This file is
- *  licensed under the Affero General Public License version 3 or later.  See
- *  the COPYRIGHT file.
- */
-
-describe("View", function() {
-  it("is the object that helps the UI", function() {
-    expect(typeof View === "object").toBeTruthy();
-  });
-});