text: (function() {
  
  ko.bindingHandlers.checked = {
      'after': ['value', 'attr'],
      'init': function (element, valueAccessor, allBindings) {
          var checkedValue = ko.pureComputed(function() {
              // Treat "value" like "checkedValue" when it is included with "checked" binding
              if (allBindings.has('checkedValue')) {
                  return ko.utils.unwrapObservable(allBindings.get('checkedValue'));
              } else if (allBindings.has('value')) {
                  return ko.utils.unwrapObservable(allBindings.get('value'));
              }
  
              return element.value;
          });
  
          function updateModel() {
              // This updates the model value from the view value.
              // It runs in response to DOM events (click) and changes in checkedValue.
              var isChecked = element.checked,
                  elemValue = useCheckedValue ? checkedValue() : isChecked;
  
              // When we're first setting up this computed, don't change any model state.
              if (ko.computedContext.isInitial()) {
                  return;
              }
  
              // We can ignore unchecked radio buttons, because some other radio
              // button will be getting checked, and that one can take care of updating state.
              if (isRadio && !isChecked) {
                  return;
              }
  
              var modelValue = ko.dependencyDetection.ignore(valueAccessor);
              if (valueIsArray) {
                  var writableValue = rawValueIsNonArrayObservable ? modelValue.peek() : modelValue;
                  if (oldElemValue !== elemValue) {
                      // When we're responding to the checkedValue changing, and the element is
                      // currently checked, replace the old elem value with the new elem value
                      // in the model array.
                      if (isChecked) {
                          ko.utils.addOrRemoveItem(writableValue, elemValue, true);
                          ko.utils.addOrRemoveItem(writableValue, oldElemValue, false);
                      }
  
                      oldElemValue = elemValue;
                  } else {
                      // When we're responding to the user having checked/unchecked a checkbox,
                      // add/remove the element value to the model array.
                      ko.utils.addOrRemoveItem(writableValue, elemValue, isChecked);
                  }
                  if (rawValueIsNonArrayObservable && ko.isWriteableObservable(modelValue)) {
                      modelValue(writableValue);
                  }
              } else {
                  ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);
              }
          };
  
          function updateView() {
              // This updates the view value from the model value.
              // It runs in response to changes in the bound (checked) value.
              var modelValue = ko.utils.unwrapObservable(valueAccessor());
  
              if (valueIsArray) {
                  // When a checkbox is bound to an array, being checked represents its value being present in that array
                  element.checked = _.includes(modelValue, checkedValue());
              } else if (isCheckbox) {
                  // When a checkbox is bound to any other value (not an array), being checked represents the value being trueish
                  element.checked = modelValue;
              } else {
                  // For radio buttons, being checked means that the radio button's value corresponds to the model value
                  element.checked = (checkedValue() === modelValue);
              }
          };
  
          var isCheckbox = element.type === "checkbox",
              isRadio = element.type === "radio";
  
          // Only bind to check boxes and radio buttons
          if (!isCheckbox && !isRadio) {
              return;
          }
  
          var rawValue = valueAccessor(),
              valueIsArray = isCheckbox && _.isArray(ko.utils.unwrapObservable(rawValue)),
              rawValueIsNonArrayObservable = !(valueIsArray && rawValue.push && rawValue.splice),
              oldElemValue = valueIsArray ? checkedValue() : undefined,
              useCheckedValue = isRadio || valueIsArray;
  
          // Set up two computeds to update the binding:
  
          // The first responds to changes in the checkedValue value and to element clicks
          ko.computed(updateModel, null, { disposeWhenNodeIsRemoved: element });
          ko.utils.registerEventHandler(element, "click", updateModel);
  
          // The second responds to changes in the model value (the one associated with the checked binding)
          ko.computed(updateView, null, { disposeWhenNodeIsRemoved: element });
  
          rawValue = undefined;
      }
  };
  ko.expressionRewriting.twoWayBindings.checked = true;
  
  ko.bindingHandlers.checkedValue = {
      'update': function (element, valueAccessor) {
          element.value = ko.utils.unwrapObservable(valueAccessor());
      }
  };
  
  })();