;(function(root) {

  "use strict";

  var GOVUK = root.GOVUK;

  function _unique(array) {
    return $.grep(array, function(el, index) {
        return index === $.inArray(el, array);
    });
  }

  // wrapper around the categories data
  var Categories = function (_categories) {
    var primaries = []

    this._containers = []
    this._categories = _categories
    this.save_last_state()
  }
  Categories.prototype.save_last_state = function () {
    this._lastState = $.extend(true, {}, this._categories)
  }
  Categories.prototype.tick_by_name = function (category_names) {

    this.save_last_state()
    $(this._categories).each(function () {
      var category = this
      var subcategories
      if ($.inArray(category.value, category_names) !== -1) {
        category.checked = !category.checked
      }
    })
  }
  Categories.prototype.all = function () {
    return this._categories
  }
  Categories.prototype.get_primaries = function () {
    var parents = []
    $.each(this._categories, function () {
      parents.push(this.parent)
    })
    return _unique(parents)
  }
  Categories.prototype.get_children_for = function (value) {
    return $(this._categories).filter(function () {
      return this.parent === value
    })
  }
  Categories.prototype.get_parent_for = function (category) {
    var category_parent = category.parent

    return $(this.get_primaries()).filter(function () { return this.value === category_parent })[0]
  }
  Categories.prototype.get_filtered_names = function (filter) {
    return $(this._categories).filter(filter).map(function () { return this.value })
  }
  Categories.prototype.get_checked = function (dedupe) {
    var results = $(this._categories).filter(function () { return this.checked })
    var unique_results = []

    if(dedupe === undefined) {
        return results
    }

    // de-dupe results
    $(results).each(function () {
      var category_name = this.value
      if ($.inArray(category_name, unique_results) === -1) {
        unique_results.push(category_name)
      }
    })
    return unique_results
  }
  Categories.prototype.diff = function (oldState, newState) {
    var diff = []

    oldState.each(function (idx) {
      var newCategory = newState[idx]
      if (this.checked !== newCategory.checked) {
        diff.push(newCategory)
      }
    })
    return diff
  }
  Categories.prototype.get_changes = function () {
    return this.diff(this._lastState, this._categories)
  }

  var categoryPicker = function () {
    var categories_data = $('#checkbox-tree__inputs input[type=checkbox]').map(function () {
      var $input = $(this)
      var $label = $input.parent()

      return {
        'value': $.trim($label.text()),
        'id': $input.attr('id'),
        'parent': $input.parents('details').find('.categories-heading').text(),
        'checked': $input.is(':checked')
      }
    })
    var globalCategories = new Categories(categories_data)

    function setCounter () {
      var checked = globalCategories.get_checked(true).length
      var suffix = (checked === 1) ? 'category' : 'categories'
      $counter.html('<strong>' + checked + '</strong> ' + suffix + ' selected.')
    }

    var $counter = $('#counter')

    function renderCategories () {
      var updatedCategories = globalCategories.get_changes()

      $(updatedCategories).each(function () {
        var $input = $('#' + this.id)
        var action = (this.checked) ? 'addClass' : 'removeClass'

        $input.attr('checked', this.checked)
        $input.parent('label')[action]('selected')
      })
      setCounter()
    }

    function setParentContextCounters () {
      var parents = globalCategories.get_primaries()
      $.each(parents, function() {
        setParentContextCounter(this)
      })
    }

    function setParentContextCounter (parentCategory) {
      var childCategories = globalCategories.get_children_for(parentCategory)
      var checkedCategories = globalCategories.get_checked()
      var checkedChildCategories = $.map(childCategories, function (category) {
        return $.inArray(category, checkedCategories) < 0 ? null : category.value
      })

      // write the message
      var parentContext = childCategories.length + ' categories'
      parentContext += (checkedChildCategories.length) ? ', ' + checkedChildCategories.length + ' selected' : ''

      // update the .categories-summary span
      $('.categories-heading:contains("' + parentCategory + '")').next().text(parentContext)
    }

    renderCategories()
    setCounter()
    setParentContextCounters()

    // make clicks on checkboxes update the categories state
    // TODO: looks like the event is triggered four times
    $('#checkbox-tree__inputs').on('click', 'label', function (evt) {
      var target = evt.target
      var targetNodeName = target.nodeName.toLowerCase()
      var categoryName

      function getLabelTextForInput (input) {
        var text = ''
        var siblings = $(input).parent().contents().each(function () {
          var childNode = this
          if (childNode.nodeType === 3) { // text node
            text += $(childNode).text()
          }
        })
        return $.trim(text)
      }

      function updateView (categoryName) {
        globalCategories.tick_by_name([categoryName])
        renderCategories()
        setParentContextCounters()
        setCounter()

      }

      if (targetNodeName === 'input') {
        categoryName = getLabelTextForInput(target)
        updateView(categoryName)
      }
    })
  }

  root.GOVUK.GDM.categoryPicker = categoryPicker
  categoryPicker()

})(window);

@@ -2938,16 +2938,335 @@
 _data)%0A%0A
+    function appendCounter(id) %7B%0A       var $_counter = $('#' + id)%0A%0A       if(!$_counter.length) %7B%0A         $('.checkbox-tree__counter')%0A           .find('div')%0A           .append($(%22%3Cp%3E%22, %7B%22id%22: id, %22role%22: %22status%22, %22aria-live%22: %22polite%22%7D))%0A%0A         $_counter = $('#' + id)%0A       %7D%0A%0A       return $_counter%0A    %7D%0A%0A
     func
@@ -3282,24 +3282,24 @@
 ounter () %7B%0A
-
       var ch
@@ -3518,20 +3518,31 @@
 unter = 
-$
+appendCounter
 ('
-#
 counter'

Add counter element to checkbox tree with JavaScript