Files @ 9b48cc94e651
Branch filter:

Location: website/www/conservancy/static/js/supporter-page.js

9b48cc94e651 6.8 KiB application/javascript Show Annotation Show as Raw Download as Raw
Bradley M. Kuhn
Continuing saga of the sizing chart problems for original shirts

Gildan removed the sizing chart entirely from their website again
after yet another redesign. Originally, we deep-linked into files in
their CDN for the charts, but it appears that in 5c72071 that I
introduced cut-and-paste error on the sizing charts. I cannot find
the original links, but finally I simply decided we'd mirror the
files in our CDN, which is where these now link to.

I suspect that I didn't do this to start for worrying about copyright
infringement, but upon second thought, I think it's very reasonably
fair use for us to distribute these images. We bought a lot of
t-shirts from Gildan and just trying to sell through.
/* Copyright (C) 2012-2013 Denver Gingerich, 
** Copyright (C) 2013-2014, 2020 Bradley M. Kuhn,
** Copyright (C) 2016, 2020 Brett Smith.
** License: GPLv3-or-later
**  Find a copy of GPL at https://sfconservancy.org/GPLv3
*/

var NEW_AMOUNT_EVENT = 'conservancy:newamount';

var flipClass = function(elem, byeClass, hiClass) {
    var classList = elem.classList;
    classList.remove(byeClass);
    classList.add(hiClass);
}

var buildAmountData = function(amountInput) {
    var amountData = {
        minAmount: parseFloat(amountInput.min),
        newAmount: parseFloat(amountInput.value),
    }
    if (amountInput.dataset.oldAmount !== undefined) {
        amountData.oldAmount = parseFloat(amountInput.dataset.oldAmount);
    }
    return amountData;
}

var supportTypeSelector = function(supportTypeHash) {
    return $(supportTypeHash + "Selector");
};

var $window = $(window);

$window.load(function() {
    /* We've sometimes published links that say #renew instead of #renewal.
       Rewrite that to work as intended. */
    if (window.location.hash === "#renew") {
        window.location.hash = "#renewal";
    }
    var $selectorLink = supportTypeSelector(window.location.hash);
    if ($selectorLink.length > 0) {
        $window.scrollTop($selectorLink.offset().top);
    }
});

$(document).ready(function() {
    // Forms start in "invalid" form, with the errors shown, so that
    // non-Javascript users see the errors by default and know what they must
    // enter.  Now we hide those for JavaScript users:
    var $formCorrectionNeeded = $('#form-correction-needed');
    $formCorrectionNeeded.addClass('hidden');

    $('form.supporter-form').each(function(index, form) {
        var $amountInput = $('input[type=number]', form).first();
        var $amountError = $('.form-error', $amountInput.parents('.supporter-form-input'));

        $amountError.on(NEW_AMOUNT_EVENT, function(event, amountData) {
            var isValid = amountData.newAmount >= amountData.minAmount;
            if (amountData.oldAmount === undefined) {
                if (isValid) {
                    $amountError.addClass('hidden');
                } else {
                    flipClass($amountInput[0], 'valid', 'invalid');
                    $amountError.removeClass('hidden');
                }
            } else if (isValid) {
                flipClass($amountInput[0], 'invalid', 'valid');
                $amountError.fadeOut();
            } else if (amountData.oldAmount >= amountData.minAmount) {
                flipClass($amountInput[0], 'valid', 'invalid');
                $amountError.fadeIn();
            }
        });

        $amountInput.on('input', function(event) {
            event.target.classList.remove('invalid');
        }).on('focusout', function(event) {
            var amountInput = event.target;
            var amountData = buildAmountData(amountInput);
            $amountError.trigger(NEW_AMOUNT_EVENT, amountData);
            amountInput.dataset.oldAmount = amountData.newAmount;
        }).trigger('focusout');

        $(form).on('submit', function(event) {
            var amountData = buildAmountData($amountInput[0]);
            if (amountData.newAmount >= amountData.minAmount) {
                $formCorrectionNeeded.addClass('hidden');
            } else {
                $formCorrectionNeeded.removeClass('hidden')
                    .css("font-weight", "bold").css("font-size", "150%");
                event.preventDefault();
            }
        });
    });

    var selectSupportType = function(event) {
        var $selectedLink = $(event.target);
        $(".supporter-type-selector a").removeClass("supporter-type-selector-selected");
        $selectedLink.addClass("supporter-type-selector-selected");
        $(".supporter-type-selection").hide();
        $(event.target.hash).show();
        $formCorrectionNeeded.addClass('hidden');
        return false;
    };
    $(".supporter-type-selector a").bind("click", selectSupportType);

    var selectSupportTypeFromHash = function() {
        return supportTypeSelector(window.location.hash).click();
    };
    $window.bind("hashchange", selectSupportTypeFromHash);
    if (selectSupportTypeFromHash().length === 0) {
        supportTypeSelector("#annual").click();
    }
    var want_id = window.location.hash.substr(1) || "do not match any id";
    var $expandable_counts = [];
    // First, build a count of expandable div sections
    $('div.expandable-section').each(function(index, section) {
        var $ourid = $(section).attr('id');
        if ($ourid == undefined) { $ourid = "__global"; }
        $expandable_counts[$ourid] = 0;
    });
    $('div[data-read-more]').each(function(index, readmore) {
        var $readmore = $(readmore)
        var $header = $readmore.prev('h3');
        if ($header.length && $header[0].id === want_id) {
            // Do nothing, leave it alone
        } else {
            var $ourid = $readmore.closest(".expandable-section" ).attr('id');
            if ($ourid == undefined) { $ourid = "__global"; }

            // Set up the link for this specific section using the text from
            // the data-read-more atrribute on the div specific to this section
            var $linkpara = $('<p><a class="read-more"></a></p>');
            var $readlink = $linkpara.children('a');
            $readlink.append($readmore.data('read-more'));
            $readlink.on('click', function(event) {
                // When clicked, we'll restore the actual text and fade it in
                // quickly, and also see if there are any remaining
                // expandable sections left in this particular expandable
                // section.  If none are left, make the "Expand all" button
                // (which lives in an 'a' anchor of the class 'expander') disappear.
                $linkpara.replaceWith($readmore);
                $readmore.fadeIn('fast');
                $expandable_counts[$ourid]--;
                if ($expandable_counts[$ourid] <= 0) {
                  $readmore.closest(".expandable-section" )
                  .children('a.expander').each(function(index, element){
                       $(element).fadeOut('slow');
                  })
                }
            });
            $readmore.hide().replaceWith($linkpara);
            $expandable_counts[$ourid]++;
        }
    });
    // Final two each's enable the "Expand All" link.
    $('a[data-expand-link-text]').each(function(index, element) {
        var $element = $(element);
        $element.append($element.data('expand-link-text'));
    });
    $('.expandable-section').each(function(index) {
        var $expandlink = $(this).children('a.expander');
        var $ourexpandablesection = $(this);
        $expandlink.on('click', function(event) {
            $expandlink.fadeOut('slow');
            $ourexpandablesection.find('.read-more').each(function(index) { $(this).click(); }); });
    });
});