docs: function createActivator(initialActiveItem, settings) {
          var activeItem = ko.observable(null);
          var activeData;
  
          settings = ensureSettings(settings);
  
          var computed = ko.computed({
              read: function () {
                  return activeItem();
              },
              write: function (newValue) {
                  computed.viaSetter = true;
                  computed.activateItem(newValue);
              }
          });
  
          computed.__activator__ = true;
  
          /**
           * The settings for this activator.
           * @property {ActivatorSettings} settings
           */
          computed.settings = settings;
          settings.activator = computed;
  
          /**
           * An observable which indicates whether or not the activator is currently in the process of activating an instance.
           * @method isActivating
           * @return {boolean}
           */
          computed.isActivating = ko.observable(false);
  
          /**
           * Determines whether or not the specified item can be deactivated.
           * @method canDeactivateItem
           * @param {object} item The item to check.
           * @param {boolean} close Whether or not to check if close is possible.
           * @return {promise}
           */
          computed.canDeactivateItem = function (item, close) {
              return canDeactivateItem(item, close, settings);
          };
  
          /**
           * Deactivates the specified item.
           * @method deactivateItem
           * @param {object} item The item to deactivate.
           * @param {boolean} close Whether or not to close the item.
           * @return {promise}
           */
          computed.deactivateItem = function (item, close) {
              return system.defer(function(dfd) {
                  computed.canDeactivateItem(item, close).then(function(canDeactivate) {
                      if (canDeactivate) {
                          deactivate(item, close, settings, dfd, activeItem);
                      } else {
                          computed.notifySubscribers();
                          dfd.resolve(false);
                      }
                  });
              }).promise();
          };
  
          /**
           * Determines whether or not the specified item can be activated.
           * @method canActivateItem
           * @param {object} item The item to check.
           * @param {object} activationData Data associated with the activation.
           * @return {promise}
           */
          computed.canActivateItem = function (newItem, activationData) {
              return canActivateItem(newItem, activeItem, settings, activationData);
          };
  
          /**
           * Activates the specified item.
           * @method activateItem
           * @param {object} newItem The item to activate.
           * @param {object} newActivationData Data associated with the activation.
           * @return {promise}
           */
          computed.activateItem = function (newItem, newActivationData) {
              var viaSetter = computed.viaSetter;
              computed.viaSetter = false;
  
              return system.defer(function (dfd) {
                  if (computed.isActivating()) {
                      dfd.resolve(false);
                      return;
                  }
  
                  computed.isActivating(true);
  
                  var currentItem = activeItem();
                  if (settings.areSameItem(currentItem, newItem, activeData, newActivationData)) {
                      computed.isActivating(false);
                      dfd.resolve(true);
                      return;
                  }
  
                  computed.canDeactivateItem(currentItem, settings.closeOnDeactivate).then(function (canDeactivate) {
                      if (canDeactivate) {
                          computed.canActivateItem(newItem, newActivationData).then(function (canActivate) {
                              if (canActivate) {
                                  system.defer(function (dfd2) {
                                      deactivate(currentItem, settings.closeOnDeactivate, settings, dfd2);
                                  }).promise().then(function () {
                                      newItem = settings.beforeActivate(newItem, newActivationData);
                                      activate(newItem, activeItem, function (result) {
                                          activeData = newActivationData;
                                          computed.isActivating(false);
                                          dfd.resolve(result);
                                      }, newActivationData);
                                  });
                              } else {
                                  if (viaSetter) {
                                      computed.notifySubscribers();
                                  }
  
                                  computed.isActivating(false);
                                  dfd.resolve(false);
                              }
                          });
                      } else {
                          if (viaSetter) {
                              computed.notifySubscribers();
                          }
  
                          computed.isActivating(false);
                          dfd.resolve(false);
                      }
                  });
              }).promise();
          };
  
          /**
           * Determines whether or not the activator, in its current state, can be activated.
           * @method canActivate
           * @return {promise}
           */
          computed.canActivate = function () {
              var toCheck;
  
              if (initialActiveItem) {
                  toCheck = initialActiveItem;
                  initialActiveItem = false;
              } else {
                  toCheck = computed();
              }
  
              return computed.canActivateItem(toCheck);
          };
  
          /**
           * Activates the activator, in its current state.
           * @method activate
           * @return {promise}
           */
          computed.activate = function () {
              var toActivate;
  
              if (initialActiveItem) {
                  toActivate = initialActiveItem;
                  initialActiveItem = false;
              } else {
                  toActivate = computed();
              }
  
              return computed.activateItem(toActivate);
          };
  
          /**
           * Determines whether or not the activator, in its current state, can be deactivated.
           * @method canDeactivate
           * @return {promise}
           */
          computed.canDeactivate = function (close) {
              return computed.canDeactivateItem(computed(), close);
          };
  
          /**
           * Deactivates the activator, in its current state.
           * @method deactivate
           * @return {promise}
           */
          computed.deactivate = function (close) {
              return computed.deactivateItem(computed(), close);
          };
  
          computed.includeIn = function (includeIn) {
              includeIn.canActivate = function () {
                  return computed.canActivate();
              };
  
              includeIn.activate = function () {
                  return computed.activate();
              };
  
              includeIn.canDeactivate = function (close) {
                  return computed.canDeactivate(close);
              };
  
              includeIn.deactivate = function (close) {
                  return computed.deactivate(close);
              };
          };
  
          if (settings.includeIn) {
              computed.includeIn(settings.includeIn);
          } else if (initialActiveItem) {
              computed.activate();
          }
  
          computed.forItems = function (items) {
              settings.closeOnDeactivate = false;
  
              settings.determineNextItemToActivate = function (list, lastIndex) {
                  var toRemoveAt = lastIndex - 1;
  
                  if (toRemoveAt == -1 && list.length > 1) {
                      return list[1];
                  }
  
                  if (toRemoveAt > -1 && toRemoveAt < list.length - 1) {
                      return list[toRemoveAt];
                  }
  
                  return null;
              };
  
              settings.beforeActivate = function (newItem) {
                  var currentItem = computed();
  
                  if (!newItem) {
                      newItem = settings.determineNextItemToActivate(items, currentItem ? items.indexOf(currentItem) : 0);
                  } else {
                      var index = items.indexOf(newItem);
  
                      if (index == -1) {
                          items.push(newItem);
                      } else {
                          newItem = items()[index];
                      }
                  }
  
                  return newItem;
              };
  
              settings.afterDeactivate = function (oldItem, close) {
                  if (close) {
                      items.remove(oldItem);
                  }
              };
  
              var originalCanDeactivate = computed.canDeactivate;
              computed.canDeactivate = function (close) {
                  if (close) {
                      return system.defer(function (dfd) {
                          var list = items();
                          var results = [];
  
                          function finish() {
                              for (var j = 0; j < results.length; j++) {
                                  if (!results[j]) {
                                      dfd.resolve(false);
                                      return;
                                  }
                              }
  
                              dfd.resolve(true);
                          }
  
                          for (var i = 0; i < list.length; i++) {
                              computed.canDeactivateItem(list[i], close).then(function (result) {
                                  results.push(result);
                                  if (results.length == list.length) {
                                      finish();
                                  }
                              });
                          }
                      }).promise();
                  } else {
                      return originalCanDeactivate();
                  }
              };
  
              var originalDeactivate = computed.deactivate;
              computed.deactivate = function (close) {
                  if (close) {
                      return system.defer(function (dfd) {
                          var list = items();
                          var results = 0;
                          var listLength = list.length;
  
                          function doDeactivate(item) {
                              computed.deactivateItem(item, close).then(function () {
                                  results++;
                                  items.remove(item);
                                  if (results == listLength) {
                                      dfd.resolve();
                                  }
                              });
                          }
  
                          for (var i = 0; i < listLength; i++) {
                              doDeactivate(list[i]);
                          }
                      }).promise();
                  } else {
                      return originalDeactivate();
                  }
              };
  
              return computed;
          };
  
          return computed;
      }