1

I have a link which allows a user to set their payment method as their default payment method if it is not already the default payment method. If they click it, I also have a short script that watches for a dom change for the clicked link, and if the href or link text becomes the href or text for the "default" payment method, it will check all of the other links on the page and make sure they are set to say "Make Default" and point to the correct URL's, etc (since one of them would say it is the default payment method).

Anyhow, my issue here is that if I update a link via jQuery, the anchor tag will be correct as far as the HTML goes, but clicking it will not allow the data-toggle to occur anymore.

Here is the initial link setup. The first time you click it, the data-toggle works, so the toggled info changes and it becomes the default. Then, another link like this is clicked, and this one would revert back into this state via my jQuery. At that point, it no longer toggles. I've tried to find a way to trigger the toggle without following through with the event, but if I stop the event, I would stop the toggle. And if I temporarily change the href, then I'm just altering it via jQuery and doing what I'm already doing.

<a class="default-billing default-billing-bank fws-ajax"
    id="<?php echo $method->bank_id; ?>"
    href="/account/billing_bank_default/<?php echo $method->bank_id; ?>"
    data-toggle-href="javascript:void(0)"
    data-toggle-html="Default">Make Default</a>

Here is the jQuery I'm using to reset the default link when another link was clicked and made default.

<script type="text/javascript">
    jQuery(document).ready(function() {
        jQuery('.default-billing').on('click', function() {
            var _this = jQuery(this);

            jQuery('.default-billing').one('DOMSubtreeModified', function() {
                //alert('Changed: ' + $("<div />").append(jQuery(this).clone()).html());
                if (jQuery(this).text() == 'Default' || jQuery(this).prop('href') == 'javascript:void(0)') {
                    //alert('Default');
                    _this.removeClass('default-billing');
                    setTimeout(updateDefaultBillingLinks(), 300);

                    _this.addClass('default-billing');
                }
            });
        });
    });

    function updateDefaultBillingLinks() {
        jQuery('.default-billing').each(function() {
            if (jQuery(this).text() == 'Default') {
                /* I am not using this part, but tried it to see if I could just toggle it manually.  I couldn't.
                jQuery(this).toggle();
                */

                jQuery(this).text('Make Default');
                jQuery(this).data('toggle-href', 'javascript:void(0)');
                jQuery(this).data('toggle-html', 'Default');

                if (jQuery(this).hasClass('.default-billing-card')) {
                    jQuery(this).prop('href', '/account/billing_card_default/' + jQuery(this).prop('id'));
                }

                if (jQuery(this).hasClass('.default-billing-bank')) {
                    jQuery(this).prop('href', '/account/billing_bank_default/' + jQuery(this).prop('id'));
                }
            }
        });
    }
</script>

UPDATE/RESOLVED

Apparently, I did have to use the .data('toggle-[attribute]'), but my other issue was that when I was checking the .hasClass(), I was putting a . in front of the class name. I had to remove that.

Final jQuery:

<script type="text/javascript">
    jQuery(document).ready(function() {
        jQuery('.default-billing').on('click', function() {
            var _this = jQuery(this);

            jQuery('.default-billing').one('DOMSubtreeModified', function() {
                if (jQuery(this).text() == 'Default' || jQuery(this).prop('href') == 'javascript:void(0)') {
                    _this.removeClass('default-billing');

                    jQuery('.default-billing').each(function() {
                        if (jQuery(this).text() == 'Default') {
                            jQuery(this).text('Make Default');
                            jQuery(this).data('toggle-href', 'javascript:void(0)');
                            jQuery(this).data('toggle-html', 'Default');

                            if (jQuery(this).hasClass('default-billing-card')) {
                                jQuery(this).prop('href', '/account/billing_card_default/' + jQuery(this).prop('id'));
                            }

                            if (jQuery(this).hasClass('default-billing-bank')) {
                                jQuery(this).prop('href', '/account/billing_bank_default/' + jQuery(this).prop('id'));
                            }
                        }
                    });

                    _this.addClass('default-billing');
                }
            });
        });
    });
</script>
2
  • Why not set everything without using timeouts and DOM event hooks? Seems overkill. Can you setup a code snip? Are you waiting for bootstrap's animations to complete? There might be an event you can tap into: getbootstrap.com/javascript/#collapse-events Commented Dec 9, 2016 at 17:49
  • @Malk I'm using the DOM event to see when the attributes are changed. I know the link was clicked, but basically, if the attributes are not changed, then the update failed and I do not proceed to run the rest of the code. I actually don't remember why I have the delay in there anymore. May be old code. I'll just take that out and probably just pull the function code back into that area. Commented Dec 9, 2016 at 18:04

2 Answers 2

1

dont use $selector.data method use $selector.attr

bootstrap being a css library depends on html attributes not html5 dataset values

so instead of

jQuery(this).data('toggle-href', 'javascript:void(0)');
jQuery(this).data('toggle-html', 'Default');

use this

jQuery(this).attr('data-toggle-href', 'javascript:void(0)');
jQuery(this).attr('data-toggle-html', 'Default');
Sign up to request clarification or add additional context in comments.

1 Comment

This is actually what I had originally, but it wasn't working. So I updated it. However, that didn't work either. :/
0

You can remove the need to monitor the DOM to see if the update was successful by calling the update yourself in javascript. Example:

$('.default-billing').on('click', function(e) {
  var _this = jQuery(this);
  e.preventDefault();
  
  if (_this.hasClass('is-default'))
    return;
  if (_this.closest('table').find('.updating').length > 0)
    return;
  
  _this.addClass('updating');
  
  //$.ajax(this.href)
  // fake Ajax call for test
  __fakeAjax(this.href)
  .then(function(resp) { setDefaultUI(_this); })
  .always( function(){ _this.removeClass('updating') });
  
});

function setDefaultUI($el){
  $el
    .text('Default')
    .addClass('is-default')
    .closest('table')
      .find('.is-default')
      .not($el)
      .text('Make Default')
      .removeClass('is-default')
}
function __fakeAjax(href) {
  console.log(`faking call to ${href}`);
  var d = $.Deferred();
  setTimeout(d.resolve, 1000);
  return d.promise();
};
.is-default {       font-weight:bold; }
.updating::after {  content: '...';   }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
  <caption>Banks
  <tr>
    <td>Bank 1
    <td><a class="default-billing default-billing-bank fws-ajax is-default" href="/account/billing_bank_default/1">Default</a>
  <tr>
    <td>Bank 2
    <td><a class="default-billing default-billing-bank fws-ajax" href="/account/billing_bank_default/2">Make Default</a>
  <tr>
    <td>Bank 3
    <td><a class="default-billing default-billing-bank fws-ajax" href="/account/billing_bank_default/3">Make Default</a>
  <tr>
    <td>Bank 4
    <td><a class="default-billing default-billing-bank fws-ajax" href="/account/billing_bank_default/4">Make Default</a>
</table>


<table>
  <caption>Cards
  <tr>
    <td>Card 1
    <td><a class="default-billing default-billing-card fws-ajax is-default" href="/account/billing_card_default/1">Default</a>
  <tr>
    <td>Card 2
    <td><a class="default-billing default-billing-card fws-ajax" href="/account/billing_card_default/2">Make Default</a>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.