diff --git a/vendor/assets/javascripts/lock-on.js b/app/assets/javascripts/discourse/lib/lock-on.js.es6
similarity index 52%
rename from vendor/assets/javascripts/lock-on.js
rename to app/assets/javascripts/discourse/lib/lock-on.js.es6
index 8ef8e7a1788..6c7a96dc44e 100644
--- a/vendor/assets/javascripts/lock-on.js
+++ b/app/assets/javascripts/discourse/lib/lock-on.js.es6
@@ -16,75 +16,70 @@
 // 1. onbeforeunload ensure we are scrolled to the right spot
 // 2. give up on the scrollbar and implement it ourselves (something that will happen)
 
-(function (exports) {
+const SCROLL_EVENTS = "scroll.lock-on touchmove.lock-on mousedown.lock-on wheel.lock-on DOMMouseScroll.lock-on mousewheel.lock-on keyup.lock-on";
 
-  var scrollEvents = "scroll.lock-on touchmove.lock-on mousedown.lock-on wheel.lock-on DOMMouseScroll.lock-on mousewheel.lock-on keyup.lock-on";
+function within(threshold, x, y) {
+  return Math.abs(x-y) < threshold;
+}
 
-  var LockOn = function(selector, options) {
+export default class LockOn {
+  constructor(selector, options) {
     this.selector = selector;
     this.options = options || {};
-  };
+    this.offsetTop = null;
+  }
 
-  LockOn.prototype.elementTop = function() {
-    var offsetCalculator = this.options.offsetCalculator,
-        selected = $(this.selector);
-
-    if (selected && selected.offset && selected.offset()) {
-      return selected.offset().top - (offsetCalculator ? offsetCalculator() : 0);
+  elementTop() {
+    const offsetCalculator = this.options.offsetCalculator;
+    if (this.offsetTop === null) {
+      this.offsetTop = offsetCalculator ? offsetCalculator() : 0;
     }
-  };
 
-  LockOn.prototype.lock = function() {
-    var self = this,
-        previousTop = this.elementTop(),
-        startedAt = new Date().getTime(),
-        i = 0;
+    const selected = $(this.selector);
+    if (selected && selected.offset && selected.offset()) {
+      return selected.offset().top - this.offsetTop;
+    }
+  }
+
+  clearLock(interval) {
+    $('body,html').off(SCROLL_EVENTS);
+    clearInterval(interval);
+  }
+
+  lock() {
+    let previousTop = this.elementTop();
+    const startedAt = new Date().getTime();
 
     $(window).scrollTop(previousTop);
 
-    var within = function(threshold,x,y) {
-      return Math.abs(x-y) < threshold;
-    };
-
-    var interval = setInterval(function() {
+    let i = 0;
+    const interval = setInterval(() => {
       i = i + 1;
 
-      var top = self.elementTop(),
-          scrollTop = $(window).scrollTop();
+      const top = this.elementTop();
+      const scrollTop = $(window).scrollTop();
 
       if (typeof(top) === "undefined") {
-        $('body,html').off(scrollEvents);
-        clearInterval(interval);
-        return;
+        return this.clearLock(interval);
       }
 
       if (!within(4, top, previousTop) || !within(4, scrollTop, top)) {
+        console.log(top, previousTop, scrollTop);
         $(window).scrollTop(top);
-        // animating = true;
-        // $('html,body').animate({scrollTop: parseInt(top,10)+'px'}, 200, 'swing', function(){
-        //   animating = false;
-        // });
         previousTop = top;
       }
 
       // We commit suicide after 3s just to clean up
-      var nowTime = new Date().getTime();
+      const nowTime = new Date().getTime();
       if (nowTime - startedAt > 1000) {
-        $('body,html').off(scrollEvents);
-        clearInterval(interval);
+        return this.clearLock(interval);
       }
-
     }, 50);
 
-    $('body,html').off(scrollEvents).on(scrollEvents, function(e){
+    $('body,html').off(SCROLL_EVENTS).on(SCROLL_EVENTS, e => {
       if ( e.which > 0 || e.type === "mousedown" || e.type === "mousewheel" || e.type === "touchmove") {
-        $('body,html').off(scrollEvents);
-        clearInterval(interval);
+        this.clearLock(interval);
       }
     });
-
-  };
-
-  exports.LockOn = LockOn;
-
-})(window);
+  }
+}
diff --git a/app/assets/javascripts/discourse/lib/url.js.es6 b/app/assets/javascripts/discourse/lib/url.js.es6
index 09a0e247980..80822a2a755 100644
--- a/app/assets/javascripts/discourse/lib/url.js.es6
+++ b/app/assets/javascripts/discourse/lib/url.js.es6
@@ -1,6 +1,6 @@
 import offsetCalculator from 'discourse/lib/offset-calculator';
+import LockOn from 'discourse/lib/lock-on';
 
-/*global LockOn:true*/
 let _jumpScheduled = false;
 const rewrites = [];
 
diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js
index 15c0c299b9c..1bb15c7a124 100644
--- a/app/assets/javascripts/main_include.js
+++ b/app/assets/javascripts/main_include.js
@@ -11,6 +11,7 @@
 //= require ./discourse/lib/notification-levels
 //= require ./discourse/lib/app-events
 //= require ./discourse/lib/offset-calculator
+//= require ./discourse/lib/lock-on
 //= require ./discourse/lib/url
 //= require ./discourse/lib/debounce
 //= require ./discourse/lib/quote
diff --git a/app/assets/javascripts/vendor.js b/app/assets/javascripts/vendor.js
index 5d6d3e6d2eb..2ada60b6250 100644
--- a/app/assets/javascripts/vendor.js
+++ b/app/assets/javascripts/vendor.js
@@ -34,7 +34,6 @@
 //= require mousetrap.js
 //= require rsvp.js
 //= require show-html.js
-//= require lock-on.js
 //= require break_string
 //= require buffered-proxy
 //= require jquery.autoellipsis-1.0.10.min.js