Chapter 7: Creating a universal watch callback

HTML

<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
    <div ng-controller="Ctrl">
        <input ng-model="foo" />
        <input ng-model="bar" />
        <div>{{ foo }}</div>
        <div>{{ bar }}</div>
        <button ng-click="logWatchers()">Log Watchers</button>
    </div>
</div>

JavaScript

angular.module('myApp', [])
.controller('Ctrl', function ($scope, $log) {
    // invoked once every time $scope.foo is modified
    $scope.$watch('foo', function (newVal, oldVal, scope) {
        // newVal is the current value of $scope.foo
        // oldVal isa the previous value of $scope.foo
        // scope === $scope
    });

    // invoked once every time $scope.bar is modified
    $scope.$watch('bar', function (newVal, oldVal, scope) {
        // newVal is the current value of $scope.bar
        // oldVal is the previous value of $scope.bar
        // scope === $scope
    });

    // invoked once every $digest cycle
    $scope.$watch(function (scope) {
        // scope === $scope
    });
    
    $scope.logWatchers = function() {
        $log.log(getWatchers());
    };
});

var getWatchers = function (element) {
    // convert to a jqLite/jQuery element
    // angular.element is idempotent
    var el = angular.element(
            // defaults to the body element
            element || document.getElementsByTagName('body')
        )
        // extract the DOM element data
      , elData = el.data()
        // initalize returned watchers array
      , watchers = [];

    // AngularJS lists watches in 3 categories
    // each contains an independent watch list
    angular.forEach([
            // general inherited scope
            elData.$scope,
            // isolate scope attached to templated directive
            elData.$isolateScope,
            // isolate scope attached to templateless directive
            elData.$isolateScopeNoTemplate
        ],
        function (scope) {
            // each element may not have a scope class attached
            if (scope) {
                // attach the watch list
                watchers = watchers.concat(scope.$$watchers || []);
            }
        }
    );

document.body.gw = 'getWatchers';

    // recurse through DOM tree
    angular.forEach(el.children(), function (childEl) {
        watchers =...