0

I'm trying to use a patience is a virtue script in combination with Ajax.

For some reason the renable() doesn't get executed. The 'wheel' keeps spinning when I hit save. The record gets saved so the Ajax call should be complete after that.

This is what I have right now:

ajax-save.js

    import $ from 'jquery';
    import { patience_virtue, renable } from './patience-is-a-virtue';
    
    let form = $('#editcontent');
    let record_id = form.data('record');
    let element = $('button[name="save"]');
    
    record_id = JSON.stringify(record_id);
    /**
     * Start of Ajaxy solution for saving
     */
    element.click(function() {
        $.ajax({
            type: 'POST',
            link: '/edit/' + record_id,
            data: $(form).serialize(),
            beforeSend: patience_virtue(element),
            complete: renable(),
        });
    });

patience-is-a-virtue.js

    import $ from 'jquery';
    
    export function patience_virtue(thisElement) {
        const thisIcon = thisElement.find('i');
    
        // Bootstrap padding / margin like `mx-2` or `pt-3`
        const addedPadding = thisIcon.attr('class').match(/[mp][tblrxy]-[0-5]/i);
        const newClass = 'fas fa-w fa-cog fa-spin ' + (addedPadding ? addedPadding : '');
    
        thisElement.attr('data-original-class', thisIcon.attr('class'));
        thisIcon.attr('class', newClass);
    
        window.setTimeout(function() {
            thisElement.attr('disabled', true);
        }, 50);
    }
    
    export function renable() {
        $('*[data-original-class]').each(function() {
            const thisIcon = $(this).find('i');
    
            $(this).attr('disabled', false);
            thisIcon.attr('class', $(this).attr('data-original-class'));
        });
    }

Edit: It seems like $(this).attr('disabled') inside renable() is undefined. But console.log($(this)) returns the following: Showcase of console log

Joossieπ
  • 15
  • 8
  • Hmm by adding those the icon doesn't change at all but it does get disabled. – Joossieπ Mar 15 '22 at 08:53
  • `complete: renable()` would run renable() immediately (before the ajax request starts) and use the return value (null) for the `complete:` callback. This is not what you want. – freedomn-m Mar 15 '22 at 09:03
  • Check that your function is being called (and when...) - either with a debugging breakpoint or a simple `console.log("reenable")` inside `renable()`. From your comment that ""icon doesn't change at all*" - the renable() function is working fine. This is because it **does** get changed by `patience_virtue()` then *immediately* changed back - both before the ajax call starts. Doesn't get re-enabled (remove disabled) as disabled is a flag attribute, so `disabled=false` is still disabled - you need to [remove the attribute](https://stackoverflow.com/questions/1785071/jquery-remove-attribute) – freedomn-m Mar 15 '22 at 09:08
  • Without seeing the markup for `$('button[name="save"]')` it's likely that it's submitting the form. Change the button to ` – freedomn-m Mar 15 '22 at 09:10
  • You're right @freedomn-m the `renable` gets called before the post. Does this mean I need to change `complete: ` to something like `success: `? Edit: Its already `type='button'` see the screenshot at the bottom for the markup – Joossieπ Mar 15 '22 at 09:13
  • 3
    No - you need to know the difference between: `callback: func` / `callback: func()` / `callback: function() { func(); }` / `callback: () => func()` - if you're not sure, then always just use `callback: function() { func(); }` so in your case, change *both* before and complete to: `beforeSend: function() { patience_virtue(element) }, complete: function() { renable() },`. complete: should be ok You should add an `error: function(jq, status, err) { console.log(status, err); }` as well, just to check for errors - but complete: should still run even if there's an error. – freedomn-m Mar 15 '22 at 09:17
  • 1
    Aha! Thanks that worked. Can you maybe send a link with some explanation of what the differences are between those callback functions? – Joossieπ Mar 15 '22 at 09:36
  • `func` assigns the `function func()` to the callback, so will be called. `func()` calls func immediately and returns the value as the callback - so `function func() { return func2 } function func2() { }` would set the callback to `func2` - most times you don't want this as your func() doesn't return a function so just runs immediately and sets nothing to callback. `function() { ... }` assigns an anonymous function to the callback, so that anon-function will only run when the callback calls it, with any methods only running at the correct time. – freedomn-m Mar 15 '22 at 09:50
  • I'm sure there's an answer with a more complete answer, here's [one](https://stackoverflow.com/a/16196908/2181514) without many details. – freedomn-m Mar 15 '22 at 09:52

0 Answers0