title: KnockoutJS: fade in after fading out something else
body: <p>Say I have a set of 3 radio buttons:</p>
  
  <pre><code>&lt;div&gt;
      &lt;label&gt;
          &lt;input type="radio" name="Who" value="Myself" 
              checked="@isMyselfChecked" data-bind="checked: who" /&gt;
          Mine
      &lt;/label&gt;
      &lt;label&gt;
          &lt;input type="radio" name="Who" value="MemberId" 
              checked="@isMemberIdChecked" data-bind="checked: who" /&gt;
          I know the member's ID
      &lt;/label&gt;
      &lt;label&gt;
          &lt;input type="radio" name="Who" value="MemberUrl" 
              checked="@isMemberUrlChecked" data-bind="checked: who" /&gt;
          I know the member's URL
      &lt;/label&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>When the user selects the first radio button (Mine/Myself), no additional input is required. However, when selecting the second or third, additional input <em>is</em> required:</p>
  
  <pre><code>&lt;div&gt;
      &lt;input type="text" name="MemberId" placeholder="Enter Member ID" 
          data-bind="toggleWho: who()" style="display: none" /&gt;
      &lt;input type="text" name="MemberUrl" placeholder="Enter Member URL" 
          data-bind="toggleWho: who()" style="display: none; width: 450px;" /&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>It is easy enough to just have <code>data-bind="visible: who() === '[MemberId|MemberUrl]'"</code> on the dependent text boxes. However, what if I want to add fade in/out transitions?</p>
  
  <p>I tried out the example custom <code>fadeVisible</code> <code>bindingHandler</code> from the knockout site, and I understand how it works. However this will fade out and fade in the text boxes at the same time. If radio <code>'MemberId'</code> is selected, and user selects <code>'MemberUrl'</code> radio, I want the <code>MemberId</code> text box to fade out <em>before</em> the <code>MemberUrl</code> text box fades in.</p>
  
  <p>Below is what I have now, and it works, but I don't think it's optimal. How else can knockout be told to not perform the fade in until a previous element has been faded out? Do I need another <code>ko.observale</code>, or possibly a <code>ko.computed</code>?</p>
  
  <pre><code>var viewModel = {
      fadeSpeed: 150,
      who: ko.observable($('input[type=radio][name=Who]:checked').val())
  };
  
  ko.bindingHandlers.toggleWho = {
      init: function (element, valueAccessor) {
          var value = valueAccessor();
          var unwrapped = ko.utils.unwrapObservable(value);
          if (unwrapped === element.name)
              $(element).show();
      },
      update: function (element, valueAccessor) {
          var value = valueAccessor();
          var unwrapped = ko.utils.unwrapObservable(value);
  
          // when selected value is myself, fade out the visible one, if any
          if (unwrapped === 'Myself') {
              $('input[type=text][name=MemberId]:visible')
                  .fadeOut(viewModel.fadeSpeed);
              $('input[type=text][name=MemberUrl]:visible')
                  .fadeOut(viewModel.fadeSpeed);
          }
  
              // when selected value is memberid, may need to fade out url first
          else if (unwrapped === 'MemberId') {
              if ($('input[type=text][name=MemberUrl]:visible').length &gt; 0) {
                  $('input[type=text][name=MemberUrl]:visible')
                      .fadeOut(viewModel.fadeSpeed, function () {
                          $('input[type=text][name=MemberId]')
                              .fadeIn(viewModel.fadeSpeed);
                      });
              } else {
                  $('input[type=text][name=MemberId]')
                      .fadeIn(viewModel.fadeSpeed);
              }
          }
  
              // when selected value is memberurl, may need to fade out id first
          else if (unwrapped === 'MemberUrl') {
              if ($('input[type=text][name=MemberId]:visible').length &gt; 0) {
                  $('input[type=text][name=MemberId]:visible')
                      .fadeOut(viewModel.fadeSpeed, function () {
                          $('input[type=text][name=MemberUrl]')
                              .fadeIn(viewModel.fadeSpeed);
                  });
              } else {
                  $('input[type=text][name=MemberUrl]')
                      .fadeIn(viewModel.fadeSpeed);
              }
          }
      }
  };
  
  ko.applyBindings(viewModel);
  </code></pre>