diff --git a/platform/commonUI/general/src/directives/MCTScroll.js b/platform/commonUI/general/src/directives/MCTScroll.js index e69de29bb2..d9abf810a1 100644 --- a/platform/commonUI/general/src/directives/MCTScroll.js +++ b/platform/commonUI/general/src/directives/MCTScroll.js @@ -0,0 +1,57 @@ +/*global define*/ + +define( + [], + function () { + 'use strict'; + + /** + * Superclass of mct-scroll-x and mct-scroll-y directives. Listens + * for scroll events and publishes their results into scope; watches + * scope and updates scroll state to match. This varies for x- and y- + * directives only by the attribute name chosen to find the expression, + * and the property (scrollLeft or scrollTop) managed within the + * element. + * @constructor + * @param $parse Angular's $parse + * @param {string} property property to manage within the HTML element + * @param {string} attribute attribute to look at for the assignable + * Angular expression + */ + function MCTScroll($parse, property, attribute) { + function link(scope, element, attrs) { + var expr = attrs[attribute], + parsed = $parse(expr); + + // Set the element's scroll to match the scope's state + function updateElement(value) { + element[0][property] = value; + } + + // Handle event; assign to scroll state to scope + function updateScope() { + parsed.assign(element[0][property]); + } + + // Initialize state in scope + updateScope(); + + // Update element state when value in scope changes + scope.$watch(expr, updateElement); + + // Update state in scope when element is scrolled + element.on('scroll', updateScope); + } + + return { + // Restrict to attributes + restrict: "A", + // Use this link function + link: link + }; + } + + return MCTScroll; + + } +); \ No newline at end of file diff --git a/platform/commonUI/general/test/directives/MCTScrollSpec.js b/platform/commonUI/general/test/directives/MCTScrollSpec.js index 7b5dfff77b..8b14606d53 100644 --- a/platform/commonUI/general/test/directives/MCTScrollSpec.js +++ b/platform/commonUI/general/test/directives/MCTScrollSpec.js @@ -27,7 +27,7 @@ define( mockParsed.assign = jasmine.createSpy('assign'); mockScope = jasmine.createSpyObj('$scope', ['$watch']); - mockElement = [{ scrollLeft: 42 }]; + mockElement = [{ testProperty: 42 }]; mockElement.on = jasmine.createSpy('on'); mockParse.andReturn(mockParsed); @@ -57,7 +57,7 @@ define( jasmine.any(Function) ); // Should have been only watch (other tests need this to be true) - expect(mockScope.$watch.calls.length).toEqual(0); + expect(mockScope.$watch.calls.length).toEqual(1); }); it("listens for scroll events", function () { @@ -66,7 +66,7 @@ define( jasmine.any(Function) ); // Should have been only listener (other tests need this to be true) - expect(mockElement.on.calls.length).toEqual(0); + expect(mockElement.on.calls.length).toEqual(1); }); it("publishes initial scroll state", function () { @@ -76,12 +76,12 @@ define( it("updates scroll state when scope changes", function () { mockScope.$watch.mostRecentCall.args[1](64); - expect(mockElement[0].scrollLeft).toEqual(64); + expect(mockElement[0].testProperty).toEqual(64); }); it("updates scope when scroll state changes", function () { - mockElement[0].scrollLeft = 12321; - mockElement.on.mostRecentCall.args({ target: mockElement[0] }); + mockElement[0].testProperty = 12321; + mockElement.on.mostRecentCall.args[1]({ target: mockElement[0] }); expect(mockParsed.assign).toHaveBeenCalledWith(12321); });