JSFiddle - React, Tailwind, and code Playground

by simonsparks

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div class="fullheight" data-ng-app="app">
    <div class="fullheight" data-ng-controller="controller">
        <h1>Size Watcher Test</h1>
        <p>A demonstration of watching changes to an element's size in AngularJS with a controllable refresh rate.</p>
        <h2>
            <label for="enabled">Enabled:</label>
            <input id="enabled" type="checkbox" data-ng-model="enabled" />
            <span>Size:</span>
            <strong data-ng-bind="info.width"></strong>
            <span>x</span>
            <strong data-ng-bind="info.height"></strong>
            <span>px</span>
        </h2>

        <div class="parent">
            <div class="directive" data-ng-if="enabled" data-width="info.width" data-height="info.height" data-rate="info.rate">
                <div class="wrapper">
                    <p>Directive enabled with size watcher service.</p>
                    <p>Updates are reflected in the model of the parent controller, as seen above.</p>
                    <p>
                        <label for="rate">Refresh rate (ms):</label>
                        <input type="number" data-ng-model="info.rate"></input>
                    </p>
                </div>
            </div>
        </div>
    </div>
</div>

CSS

html, body, .fullheight {
    height: 100%;
}

.parent {
    height: 50%;
    width: 50%;
    margin: auto;
    border: 1px solid;
    border-radius: 5px;
}

.directive {
    height: 100%;
    width: 100%;
}

.wrapper {
    margin: 10px;
    padding:10px;
}

JavaScript

angular.module('app', [])
    .factory('sizeWatcher', ['$interval', function($interval) {
        return function (element, rate) {
            var self = this;
            (self.update = function() { self.dimensions = [element.offsetWidth, element.offsetHeight]; })();
            self.group = [function() { return self.dimensions[0]; }, function() { return self.dimensions[1]; }];
            self.monitor = $interval(self.update, rate);
            self.cancel = function() { $interval.cancel(self.monitor); };
        }
    }])

    .controller('controller', ['$scope', function($scope) {
        $scope.enabled = true;
        $scope.info = {
            width: 0,
            height: 0,
            rate: 200
        };
    }])

    .directive('directive', ['sizeWatcher', function(sizeWatcher) {
        return {
            restrict: 'C',
            scope: {
                width: '=',
                height: '=',
                rate: '='
            },
            link: function($scope, element) {
                var parent = element[0],
                    watcher, groupWatcher,
                    cancel = function() {
                        if(watcher) watcher.cancel();
                        if(groupWatcher) groupWatcher();
                    },
                    update = function() {
                        cancel();
                        watcher = new sizeWatcher(parent, $scope.rate);
                        $scope.$watchGroup(watcher.group, function(values) {
                            $scope.width = values[0];
                            $scope.height = values[1];
                        });
                    };
                
                $scope.$watch('rate', update);
                $scope.$on('$destroy', cancel);
            }
        }
    }]);