<commit_before>define([
    'jquery',
    'logger',
    'kernel',
    'jabbr/components/external-status.lastfm',
    'jabbr/components/external-status.trakt'
], function ($, Logger, kernel, lastfm, trakt) {
    var logger = new Logger('jabbr/components/external-status'),
        client = null,
        object = null;

    logger.trace('loaded');

    var initialize = function () {
        var last = {
            type: null,
            text: null,
            timestamp: null
        };

        function publish(type, text, timestamp, interval) {
            if (last.type != type || last.text != text) {
                // If we are changing from one type to another
                if (last.type !== null && type !== null && last.type != type) {
                    logger.trace('changing status type from ' + last.type + ' to ' + type);
                    // Games trump everything
                    if (last.type == 'game') {
                        return;
                    }
                    //  Video trumps music
                    if (last.type == 'video' && type == 'music') {
                        return;
                    }
                }

                logger.trace('publishing: "' + text + '" (' + type + ')');

                if (text === null) {
                    type = null;
                }

                client.chat.server.publishExternalStatus(type, text, timestamp, interval);

                last = {
                    type: type,
                    text: text,
                    timestamp: timestamp
                };
            }
        }

        return {
            activate: function () {
                client = kernel.get('jabbr/client');

                lastfm.activate();
                trakt.activate();

                logger.trace('activated');
            },

            publish: publish
        };
    };

    return function () {
        if (object === null) {
            lastfm = lastfm();
            trakt = trakt();

            object = initialize();
            kernel.bind('jabbr/components/external-status', object);
        }

        return object;
    };
});<commit_msg>Fix for trakt external status provider clearing a music status when nothing is being watched.<commit_after>define([
    'jquery',
    'logger',
    'kernel',
    'jabbr/components/external-status.lastfm',
    'jabbr/components/external-status.trakt'
], function ($, Logger, kernel, lastfm, trakt) {
    var logger = new Logger('jabbr/components/external-status'),
        client = null,
        object = null;

    logger.trace('loaded');

    var initialize = function () {
        var last = {
            type: null,
            text: null,
            timestamp: null
        };

        function publish(type, text, timestamp, interval) {
            if (last.type != type || last.text != text) {
                // If we are changing from one type to another
                if (last.type !== null && type !== null && last.type != type) {
                    // Ignore 'nothing' publish
                    if (last.text !== null && text === null) {
                        return;
                    }

                    logger.trace('changing status type from ' + last.type + ' to ' + type);
                    // Games trump everything
                    if (last.type == 'game') {
                        return;
                    }
                    //  Video trumps music
                    if (last.type == 'video' && type == 'music') {
                        return;
                    }
                }

                logger.trace('publishing: "' + text + '" (' + type + ')');

                if (text === null) {
                    type = null;
                }

                client.chat.server.publishExternalStatus(type, text, timestamp, interval);

                last = {
                    type: type,
                    text: text,
                    timestamp: timestamp
                };
            }
        }

        return {
            activate: function () {
                client = kernel.get('jabbr/client');

                lastfm.activate();
                trakt.activate();

                logger.trace('activated');
            },

            publish: publish
        };
    };

    return function () {
        if (object === null) {
            lastfm = lastfm();
            trakt = trakt();

            object = initialize();
            kernel.bind('jabbr/components/external-status', object);
        }

        return object;
    };
});<|endoftext|>


<commit_before>RJSDemoApp.applyToolbarHandlers = function () {

    // Library panel
    $("#toc-btn").off("click");
    $("#library-btn").on("click", function () {
        RJSDemoApp.toggleLibraryPanel();
    });

    // TOC
    $("#toc-btn").off("click");
    $("#toc-btn").on("click", function () {
        RJSDemoApp.toggleTOCPanel();
    });

	// Decrease font size
	(function() {
		var $decreaseFont = $("#decrease-font-btn");

		$decreaseFont.off("click");
		$decreaseFont.on("click", function() {
			var settings = RJSDemoApp.epubViewer.getViewerSettings()
			RJSDemoApp.epubViewer.setFontSize(settings.fontSize - 2);
		});
	})();

	// Increase font size
	(function() {
		var $increaseFont = $("#increase-font-btn");

		$increaseFont.off("click");
		$increaseFont.on("click", function() {
			var settings = RJSDemoApp.epubViewer.getViewerSettings()
			RJSDemoApp.epubViewer.setFontSize(settings.fontSize + 2);
		});
	})();

    // Prev
    // Remove any existing click handlers
    $("#previous-page-btn").off("click");
    $("#previous-page-btn").on("click", function () {

        if (RJSDemoApp.epub.pageProgressionDirection() === "rtl") {
            RJSDemoApp.epubViewer.nextPage(function () {
                console.log("the page turned");
            });
        }
        else {
            href = e.currentTarget.attributes["href"].value;
        }

        // It's a CFI
        if (href.match("epubcfi")) {

            href = href.trim();
            splitHref = href.split("#");

            // RJSDemoApp.epubViewer.showPageByCFI(splitHref[1], function () {
            //     console.log("Showed the page using a CFI");
            // }, this);
        }
        // It's a regular id
        else {

            // Get the hash id if it exists
            href = href.trim();
            splitHref = href.split("#");

            spineIndex = RJSDemoApp.epub.getSpineIndexByHref(href);
            if (splitHref[1] === undefined) {
                // RJSDemoApp.epubViewer.showSpineItem(spineIndex, function () {
                //     console.log("Spine index shown: " + splitHref[0]);
                // });
            }
            else {
                // RJSDemoApp.epubViewer.showPageByElementId(spineIndex, splitHref[1], function () {
                //     console.log("Page shown: href: " + splitHref[0] + " & hash id: " + splitHref[1]);
                // });
            }
        }
    };

    RJSDemoApp.tocLinkClicked = function (e) {

        RJSDemoApp.epubLinkClicked(e);
    };

    RJSDemoApp.toggleLibraryPanel = function () {

        if (RJSDemoApp.viewerPreferences.libraryIsVisible) {
            $("#library-panel").hide();
            RJSDemoApp.viewerPreferences.libraryIsVisible = false;
        }
        else {
            $("#toc-panel").hide();
            $("#library-panel").show();
            RJSDemoApp.viewerPreferences.tocIsVisible = false;
            RJSDemoApp.viewerPreferences.libraryIsVisible = true;
        }
    };

    RJSDemoApp.toggleTOCPanel = function () {

        if (RJSDemoApp.viewerPreferences.tocIsVisible) {
            $("#toc-panel").hide();
            RJSDemoApp.viewerPreferences.tocIsVisible = false;
        }
        else {
            $("#library-panel").hide();
            $("#toc-panel").show();
            RJSDemoApp.viewerPreferences.tocIsVisible = true;
            RJSDemoApp.viewerPreferences.libraryIsVisible = false;
        }
    };

    RJSDemoApp.toggleLayout = function () {

        if (RJSDemoApp.viewerPreferences.syntheticLayout) {
            RJSDemoApp.epubViewer.updateSettings({ "isSyntheticSpread" : false });
            RJSDemoApp.viewerPreferences.syntheticLayout = false;
        }
        else {
            RJSDemoApp.epubViewer.updateSettings({ "isSyntheticSpread" : true });
            RJSDemoApp.viewerPreferences.syntheticLayout = true;
        }
    };

    return RJSDemoApp;
});
<commit_msg>Fix test site event handling after the merge of requirejs-experiment-almond.<commit_after>define(['jquery'], function ($) {
    RJSDemoApp.applyToolbarHandlers = function () {

        // Library panel
        $("#toc-btn").off("click");
        $("#library-btn").on("click", function () {
            RJSDemoApp.toggleLibraryPanel();
        });

        // TOC
        $("#toc-btn").off("click");
        $("#toc-btn").on("click", function () {
            RJSDemoApp.toggleTOCPanel();
        });

        // Decrease font size
        (function () {
            var $decreaseFont = $("#decrease-font-btn");

            $decreaseFont.off("click");
            $decreaseFont.on("click", function () {
                // ReadiumSDK.Views.ReaderView doesn't expose a method to retrieve current settings,
                // so at the moment differential changes to fontSize cannot be implemented:
                //var settings = RJSDemoApp.epubViewer.getViewerSettings()
                //RJSDemoApp.epubViewer.setFontSize(settings.fontSize - 2);
                console.log('differential changes to fontSize not supported with the ReadiumSDK version used.');
            });
        })();

        // Increase font size
        (function () {
            var $increaseFont = $("#increase-font-btn");

            $increaseFont.off("click");
            $increaseFont.on("click", function () {
                // ReadiumSDK.Views.ReaderView doesn't expose a method to retrieve current settings,
                // so at the moment differential changes to fontSize cannot be implemented:
                //var settings = RJSDemoApp.epubViewer.getViewerSettings()
                //RJSDemoApp.epubViewer.setFontSize(settings.fontSize + 2);
                console.log('differential changes to fontSize not supported with the ReadiumSDK version used.');

            });
        })();

        // Prev
        // Remove any existing click handlers
        $("#previous-page-btn").off("click");
        $("#previous-page-btn").on("click", function () {
            RJSDemoApp.epubViewer.openPageLeft();
        });

        // Next
        // Remove any existing click handlers
        $("#next-page-btn").off("click");
        $("#next-page-btn").on("click", function () {
            RJSDemoApp.epubViewer.openPageRight();
        });

        // Layout
        $("#toggle-synthetic-btn").off("click");
        $("#toggle-synthetic-btn").on("click", function () {
            RJSDemoApp.toggleLayout();
        });
    };

    RJSDemoApp.epubLinkClicked = function (e) {

        var href;
        var splitHref;
        var spineIndex;
        e.preventDefault();

        // Check for both href and xlink:href attribute and get value
        if (e.currentTarget.attributes["xlink:href"]) {
            href = e.currentTarget.attributes["xlink:href"].value;
        }
        else {
            href = e.currentTarget.attributes["href"].value;
        }

        // It's a CFI
        if (href.match("epubcfi")) {

            href = href.trim();
            splitHref = href.split("#");

            // RJSDemoApp.epubViewer.showPageByCFI(splitHref[1], function () {
            //     console.log("Showed the page using a CFI");
            // }, this);
        }
        // It's a regular id
        else {

            // Get the hash id if it exists
            href = href.trim();
            splitHref = href.split("#");

            spineIndex = RJSDemoApp.epub.getSpineIndexByHref(href);
            if (splitHref[1] === undefined) {
                // RJSDemoApp.epubViewer.showSpineItem(spineIndex, function () {
                //     console.log("Spine index shown: " + splitHref[0]);
                // });
            }
            else {
                // RJSDemoApp.epubViewer.showPageByElementId(spineIndex, splitHref[1], function () {
                //     console.log("Page shown: href: " + splitHref[0] + " & hash id: " + splitHref[1]);
                // });
            }
        }
    };

    RJSDemoApp.tocLinkClicked = function (e) {

        RJSDemoApp.epubLinkClicked(e);
    };

    RJSDemoApp.toggleLibraryPanel = function () {

        if (RJSDemoApp.viewerPreferences.libraryIsVisible) {
            $("#library-panel").hide();
            RJSDemoApp.viewerPreferences.libraryIsVisible = false;
        }
        else {
            $("#toc-panel").hide();
            $("#library-panel").show();
            RJSDemoApp.viewerPreferences.tocIsVisible = false;
            RJSDemoApp.viewerPreferences.libraryIsVisible = true;
        }
    };

    RJSDemoApp.toggleTOCPanel = function () {

        if (RJSDemoApp.viewerPreferences.tocIsVisible) {
            $("#toc-panel").hide();
            RJSDemoApp.viewerPreferences.tocIsVisible = false;
        }
        else {
            $("#library-panel").hide();
            $("#toc-panel").show();
            RJSDemoApp.viewerPreferences.tocIsVisible = true;
            RJSDemoApp.viewerPreferences.libraryIsVisible = false;
        }
    };

    RJSDemoApp.toggleLayout = function () {

        if (RJSDemoApp.viewerPreferences.syntheticLayout) {
            RJSDemoApp.epubViewer.updateSettings({ "isSyntheticSpread": false });
            RJSDemoApp.viewerPreferences.syntheticLayout = false;
        }
        else {
            RJSDemoApp.epubViewer.updateSettings({ "isSyntheticSpread": true });
            RJSDemoApp.viewerPreferences.syntheticLayout = true;
        }
    };

    return RJSDemoApp;
});
<|endoftext|>


<commit_before>import React from 'react';

const friday = [{
    start: '6:00 PM',
    name: 'Check in begins 📋',
    info: 'Loeb Playhouse'
},{
    start: '8:00 PM',
    name: 'Opening Ceremonies 🎤',
    info: 'Loeb Playhouse'
},{
    start: '9:00 PM',
    name: 'Team assembly 🤝',
    info: 'CoRec Black & Gold Gyms'
},{
    start: '9:30 PM',
    name: 'Dinner from Moe\'s 🌮',
    info: 'taco bar (yes there\'s  queso)'
},{
    start: '10:00 PM',
    name: 'Hacking Begins 💻'
},{
    start: '11:59 PM',
    name: 'Showers close 🚿'
}];

let saturday = [{
    start: '3:00 AM',
    name: 'Late Night Snack'
},{
    start: '8:00 AM',
    name: 'Breakfast 🥓',
    info: 'eggs, potatoes, bacon, fruit, bagels'
},{
    start: '8:00 AM',
    name: 'Showers reopen 🚿'
},{
    start: '10:00 AM',
    name: 'A Peek into the Decentralized Future with Blockchains ⛓',
    info: 'CoRec 2265'
},{
    start: '11:30 AM',
    name: 'Yoga 🤸'
},{
    start: '12:30 PM',
    name: 'Lunch - Pasta Bar 🍝',
    info: 'chicken, marinara, alfredo, veggies, salad, rolls'
},{
    start: '1:00 PM',
    name: 'Snack 🍿'
},{
    start: '1:30 PM',
    name: 'Yoga 🤸'
},{
    start: '3:00 PM',
    name: 'The New Frontiers in Systems Level Data Sciences and Human Space Exploration 🚀',
    info: 'CoRec 2265'
},{
    start: '4:30 PM',
    name: 'MLH Cup Stacking 🎲'
},{
    start: '6:00 PM',
    name: 'Dinner from Hotbox 🍕',
    info: 'pizza, breadsticks, salad'
},{
    start: '10:00 PM',
    name: 'Donuts! 🍩 '
},{
    start: '11:59 PM',
    name: 'Showers close🚿'
}];

let sunday = [{
    start: '1:00 AM',
    name: 'Late Night Snack 🍿'
},{
    start: '8:00 AM',
    name: 'Breakfast 🍳',
    info: 'egg casseroles, potatoes, fruit, yogurt, bagels, pastries'
},{
    start: '9:30 AM',
    name: 'Hacking Ends 🛑'
},{
    start: '10:00 AM',
    name: 'Expo Begins 📔'
},{
    start: '10:00 AM',
    name: 'Showers reopen 🚿'
},{
    start: '11:30 AM',
    name: 'Lunch from Potbelly 🍞',
    info: 'sandwiches'
},{
    start: '1:00 PM',
    name: 'Closing Ceremonies 🎭',
    info: 'Loeb Playhouse'
},{
    start: '2:30 PM',
    name: 'Buses Depart 🚌',
    info: 'Loeb Playhouse'
}];

const ScheduleDay =  ({dayData, title}) =>

{title}

        { dayData.map(item =>

{item.start}

{item.name}
{item.info}

        )}

;

const Schedule = () => (

Schedule

      <ScheduleDay dayData={friday} title="Friday (9/29)"/>
      <ScheduleDay dayData={saturday} title="Saturday (9/30)"/>
      <ScheduleDay dayData={sunday} title="Sunday (10/1)"/>

);

export default Schedule;
<commit_msg>add coffee to schedue<commit_after>import React from 'react';

const friday = [{
    start: '6:00 PM',
    name: 'Check in begins 📋',
    info: 'Loeb Playhouse'
},{
    start: '8:00 PM',
    name: 'Opening Ceremonies 🎤',
    info: 'Loeb Playhouse'
},{
    start: '9:00 PM',
    name: 'Team assembly 🤝',
    info: 'CoRec Black & Gold Gyms'
},{
    start: '9:30 PM',
    name: 'Dinner from Moe\'s 🌮',
    info: 'taco bar (yes there\'s  queso)'
},{
    start: '10:00 PM',
    name: 'Hacking Begins 💻'
},{
    start: '11:59 PM',
    name: 'Showers close 🚿'
}];

let saturday = [{
    start: '3:00 AM',
    name: 'Late Night Snack'
},{
    start: '8:00 AM',
    name: 'Breakfast 🥓',
    info: 'eggs, potatoes, bacon, fruit, bagels'
},{
    start: '8:00 AM',
    name: 'Showers reopen 🚿'
},{
    start: '8:00 AM',
    name: 'Coffee Bar Opens ☕'
},{
    start: '10:00 AM',
    name: 'A Peek into the Decentralized Future with Blockchains ⛓',
    info: 'CoRec 2265'
},{
    start: '11:30 AM',
    name: 'Yoga 🤸'
},{
    start: '12:30 PM',
    name: 'Lunch - Pasta Bar 🍝',
    info: 'chicken, marinara, alfredo, veggies, salad, rolls'
},{
    start: '1:00 PM',
    name: 'Snack 🍿'
},{
    start: '1:30 PM',
    name: 'Yoga 🤸'
},{
    start: '3:00 PM',
    name: 'The New Frontiers in Systems Level Data Sciences and Human Space Exploration 🚀',
    info: 'CoRec 2265'
},{
    start: '4:30 PM',
    name: 'MLH Cup Stacking 🎲2'
},{
    start: '6:00 PM',
    name: 'Dinner from Hotbox 🍕',
    info: 'pizza, breadsticks, salad'
},{
    start: '10:00 PM',
    name: 'Donuts! 🍩 '
},{
    start: '11:59 PM',
    name: 'Showers close🚿'
},{
    start: '11:59 PM',
    name: 'Coffee Bar Closes ☕'
}];

let sunday = [{
    start: '1:00 AM',
    name: 'Late Night Snack 🍿'
},{
    start: '8:00 AM',
    name: 'Breakfast 🍳',
    info: 'egg casseroles, potatoes, fruit, yogurt, bagels, pastries'
},{
    start: '9:30 AM',
    name: 'Hacking Ends 🛑'
},{
    start: '10:00 AM',
    name: 'Expo Begins 📔'
},{
    start: '10:00 AM',
    name: 'Showers reopen 🚿'
},{
    start: '11:30 AM',
    name: 'Lunch from Potbelly 🍞',
    info: 'sandwiches'
},{
    start: '1:00 PM',
    name: 'Closing Ceremonies 🎭',
    info: 'Loeb Playhouse'
},{
    start: '2:30 PM',
    name: 'Buses Depart 🚌',
    info: 'Loeb Playhouse'
}];

const ScheduleDay =  ({dayData, title}) =>

{title}

        { dayData.map(item =>

{item.start}

{item.name}
{item.info}

        )}

;

const Schedule = () => (

Schedule

      <ScheduleDay dayData={friday} title="Friday (9/29)"/>
      <ScheduleDay dayData={saturday} title="Saturday (9/30)"/>
      <ScheduleDay dayData={sunday} title="Sunday (10/1)"/>

);

export default Schedule;
<|endoftext|>


<commit_before>var sfa = sfa || {};

sfa.homePage = {
    init: function () {
        this.startButton();
        this.toggleRadios();
    },
    startButton: function () {
        var that = this;
        $('#submit-button').on('click touchstart', function (e) {
            var isYesClicked = $('#have-everything').prop('checked'),
                errorShown = $('body').data('shownError') || false;
            if (!isYesClicked && !errorShown) {
                e.preventDefault();
                that.showError();
            }
        });
    },
    showError: function() {
        $('.error-message').removeClass("js-hidden").attr("aria-hidden");
        $('#what-you-need-form').addClass("error");
        $('body').data('shownError', true);
    },
    toggleRadios: function () {
        var radios = $('input[type=radio][name=everything-you-need]');
        radios.on('change', function () {

            radios.each(function () {
                if ($(this).prop('checked')) {
                    var target = $(this).parent().data("target");
                    $("#" + target).removeClass("js-hidden").attr("aria-hidden");
                } else {
                    var target = $(this).parent().data("target");
                    $("#" + target).addClass("js-hidden").attr("aria-hidden", "true");
                }
            });

        });
    }
}

sfa.backLink = {
    init: function () {
        var backLink = $('<a>')
            .attr({ 'href': '#', 'class': 'link-back' })
            .text('Back')
            .on('click', function (e) { window.history.back(); e.preventDefault(); })
            .appendTo('#js-breadcrumbs');
    }
}

sfa.forms = {
    init: function () {
        this.preventDoubleSubmit();
    },
    preventDoubleSubmit: function () {
        var forms = $('form').not('.has-client-side-validation');
        forms.on('submit', function (e) {
            var button = $(this).find('.button');
            button.attr('disabled', 'disabled');
            setTimeout(function () {
                button.removeAttr('disabled');
            }, 20000);
        });
    }
}

sfa.navigation = {
    elems: {
        userNav: $('nav#user-nav > ul'),
        levyNav: $('ul#global-nav-links')
    },
    init: function () {
        this.setupMenus(this.elems.userNav);
        this.setupEvents(this.elems.userNav);
        this.linkSettings();
    },
    setupMenus: function (menu) {
        menu.find('ul').addClass("js-hidden").attr("aria-hidden", "true");
    },
    setupEvents: function (menu) {
        var that = this;
        menu.find('li.has-sub-menu > a').on('click', function (e) {
            var $that = $(this);
            that.toggleMenu($that, $that.next('ul'));
            e.stopPropagation();
            e.preventDefault();
        });
    },
    toggleMenu: function (link, subMenu) {
        var $li = link.parent();
        if ($li.hasClass("open")) {
            // Close menu
            $li.removeClass("open");
            subMenu.addClass("js-hidden").attr("aria-hidden", "true");
        } else {
            // Open menu
            this.closeAllOpenMenus();
            $li.addClass("open");
            subMenu.removeClass("js-hidden").attr("aria-hidden", "false");
        }
    },
    closeAllOpenMenus: function () {
        this.elems.userNav.find('li.has-sub-menu.open').removeClass('open').find('ul').addClass("js-hidden").attr("aria-hidden", "true");
        this.elems.levyNav.find('li.open').removeClass('open').addClass("js-hidden").attr("aria-hidden", "true");
    },
    linkSettings: function () {
        var $settingsLink = $('a#link-settings'),
            that = this;
        this.toggleUserMenu();
        $settingsLink.attr("aria-hidden", "false");
        $settingsLink.on('click touchstart', function (e) {
            var target = $(this).attr('href');
            $(this).toggleClass('open');
            that.toggleUserMenu();
            e.preventDefault();
        });
    },
    toggleUserMenu: function () {
        var $userNavParent = this.elems.userNav.parent();
        if ($userNavParent.hasClass("close")) {
            //open it
            $userNavParent.removeClass("close").attr("aria-hidden", "false");
        } else {
            // close it
            $userNavParent.addClass("close").attr("aria-hidden", "true");
        }
    }
}

if ($('#js-breadcrumbs')) {
    sfa.backLink.init();
}

sfa.navigation.init();
sfa.forms.init();

var selectionButtons = new GOVUK.SelectionButtons("label input[type='radio'], label input[type='checkbox']");<commit_msg>Datalayer pushes<commit_after>var sfa = sfa || {};

sfa.homePage = {
    init: function () {
        this.startButton();
        this.toggleRadios();
    },
    startButton: function () {
        var that = this;
        $('#submit-button').on('click touchstart', function (e) {
            var isYesClicked = $('#have-everything').prop('checked'),
                errorShown = $('body').data('shownError') || false;
            if (!isYesClicked && !errorShown) {
                e.preventDefault();
                that.showError();
            }
        });
    },
    showError: function() {
        $('.error-message').removeClass("js-hidden").attr("aria-hidden");
        $('#what-you-need-form').addClass("error");
        $('body').data('shownError', true);
    },
    toggleRadios: function () {
        var radios = $('input[type=radio][name=everything-you-need]');
        radios.on('change', function () {

            radios.each(function () {
                if ($(this).prop('checked')) {
                    var target = $(this).parent().data("target");
                    $("#" + target).removeClass("js-hidden").attr("aria-hidden");
                } else {
                    var target = $(this).parent().data("target");
                    $("#" + target).addClass("js-hidden").attr("aria-hidden", "true");
                }
            });

        });
    }
}

sfa.backLink = {
    init: function () {
        var backLink = $('<a>')
            .attr({ 'href': '#', 'class': 'link-back' })
            .text('Back')
            .on('click', function (e) { window.history.back(); e.preventDefault(); })
            .appendTo('#js-breadcrumbs');
    }
}

sfa.forms = {
    init: function () {
        this.preventDoubleSubmit();
    },
    preventDoubleSubmit: function () {
        var forms = $('form').not('.has-client-side-validation');
        forms.on('submit', function (e) {
            var button = $(this).find('.button');
            button.attr('disabled', 'disabled');
            setTimeout(function () {
                button.removeAttr('disabled');
            }, 20000);
        });
    }
}

sfa.navigation = {
    elems: {
        userNav: $('nav#user-nav > ul'),
        levyNav: $('ul#global-nav-links')
    },
    init: function () {
        this.setupMenus(this.elems.userNav);
        this.setupEvents(this.elems.userNav);
        this.linkSettings();
    },
    setupMenus: function (menu) {
        menu.find('ul').addClass("js-hidden").attr("aria-hidden", "true");
    },
    setupEvents: function (menu) {
        var that = this;
        menu.find('li.has-sub-menu > a').on('click', function (e) {
            var $that = $(this);
            that.toggleMenu($that, $that.next('ul'));
            e.stopPropagation();
            e.preventDefault();
        });
    },
    toggleMenu: function (link, subMenu) {
        var $li = link.parent();
        if ($li.hasClass("open")) {
            // Close menu
            $li.removeClass("open");
            subMenu.addClass("js-hidden").attr("aria-hidden", "true");
        } else {
            // Open menu
            this.closeAllOpenMenus();
            $li.addClass("open");
            subMenu.removeClass("js-hidden").attr("aria-hidden", "false");
        }
    },
    closeAllOpenMenus: function () {
        this.elems.userNav.find('li.has-sub-menu.open').removeClass('open').find('ul').addClass("js-hidden").attr("aria-hidden", "true");
        this.elems.levyNav.find('li.open').removeClass('open').addClass("js-hidden").attr("aria-hidden", "true");
    },
    linkSettings: function () {
        var $settingsLink = $('a#link-settings'),
            that = this;
        this.toggleUserMenu();
        $settingsLink.attr("aria-hidden", "false");
        $settingsLink.on('click touchstart', function (e) {
            var target = $(this).attr('href');
            $(this).toggleClass('open');
            that.toggleUserMenu();
            e.preventDefault();
        });
    },
    toggleUserMenu: function () {
        var $userNavParent = this.elems.userNav.parent();
        if ($userNavParent.hasClass("close")) {
            //open it
            $userNavParent.removeClass("close").attr("aria-hidden", "false");
        } else {
            // close it
            $userNavParent.addClass("close").attr("aria-hidden", "true");
        }
    }
}

if ($('#js-breadcrumbs')) {
    sfa.backLink.init();
}

sfa.navigation.init();
sfa.forms.init();

var selectionButtons = new GOVUK.SelectionButtons("label input[type='radio'], label input[type='checkbox']");

// DataLayer pushes when form validation message is shown

$(window).load(function () {
    var errorSummary = $('#content .error-summary');
    var pageTitle = $('h1.heading-xlarge').text();
    errorSummary.each(function () {
      var dataLayerObj
      var numberOfErrors = $(this).find('ul li').length;
      var validationMessage = "Form validation";
      if (numberOfErrors === 1) {
        validationMessage = $(this).find('a').eq(0).text();
      }
      dataLayerObj = {
        event: 'form submission error',
        page: pageTitle,
        message: validationMessage
      }
      window.dataLayer.push(dataLayerObj)
    });
  });<|endoftext|>


<commit_before>import React from 'react'
import { debounce, isEmpty } from 'lodash'
import { KeyControlledItemList } from './KeyControlledList'
import { getKeyCode, keyMap } from '../util/textInput'
import { NonLinkAvatar } from './Avatar'
import cx from 'classnames'
const { array, bool, string, func } = React.PropTypes

export default class TagInput extends React.Component {
  static propTypes = {
    tags: array,
    type: string,
    choices: array,
    handleInput: func.isRequired,
    onSelect: func,
    onRemove: func,
    allowNewTags: bool,
    placeholder: string,
    filter: func,
    className: string
  }

  resetInput () {
    this.refs.input.value = ''
    this.props.handleInput('')
  }

  handleKeys = event => {
    let { allowNewTags, onSelect, handleInput, filter } = this.props
    const keyCode = getKeyCode(event)

    if (this.refs.list) {
      this.refs.list.handleKeys(event)

      // if the current input brings up search results, but you wish to enter
      // the tag as-is rather than choosing a search result, you can press
      // Escape to clear the results, then press Enter to select what you've
      // typed
      if (allowNewTags && keyCode === keyMap.ESC) handleInput('')
      return
    } else if (allowNewTags && keyCode === keyMap.ENTER) {
      let { value } = event.target
      onSelect({id: value, name: value})
      this.resetInput()
      return
    }

    if (filter) filter(event)
  }

  select = choice => {
    this.props.onSelect(choice)
    this.resetInput()
  }

  remove = tag => event => {
    this.props.onRemove(tag)
    event.preventDefault()
  }

  focus = () => {
    this.refs.input.focus()
  }

  handleChange = debounce(value => {
    this.props.handleInput(value)
  }, 200)

  render () {
    let { choices, tags, placeholder, className } = this.props
    if (!tags) tags = []
    if (!placeholder) placeholder = 'Type...'

    return

        {tags.map(t =>

          {t.avatar_url && <NonLinkAvatar person={t}/>}
          {t.label || t.name}
          ×

)}

      <input ref='input' type='text' placeholder={placeholder}
        onChange={event => this.handleChange(event.target.value)}
        onKeyDown={this.handleKeys}/>

      {!isEmpty(choices) &&

        <KeyControlledItemList className='dropdown-menu' ref='list' items={choices} onChange={this.select}/>

}

  }
}
<commit_msg>set spellcheck=false on TagInput<commit_after>import React from 'react'
import { debounce, isEmpty } from 'lodash'
import { KeyControlledItemList } from './KeyControlledList'
import { getKeyCode, keyMap } from '../util/textInput'
import { NonLinkAvatar } from './Avatar'
import cx from 'classnames'
const { array, bool, string, func } = React.PropTypes

export default class TagInput extends React.Component {
  static propTypes = {
    tags: array,
    type: string,
    choices: array,
    handleInput: func.isRequired,
    onSelect: func,
    onRemove: func,
    allowNewTags: bool,
    placeholder: string,
    filter: func,
    className: string
  }

  resetInput () {
    this.refs.input.value = ''
    this.props.handleInput('')
  }

  handleKeys = event => {
    let { allowNewTags, onSelect, handleInput, filter } = this.props
    const keyCode = getKeyCode(event)

    if (this.refs.list) {
      this.refs.list.handleKeys(event)

      // if the current input brings up search results, but you wish to enter
      // the tag as-is rather than choosing a search result, you can press
      // Escape to clear the results, then press Enter to select what you've
      // typed
      if (allowNewTags && keyCode === keyMap.ESC) handleInput('')
      return
    } else if (allowNewTags && keyCode === keyMap.ENTER) {
      let { value } = event.target
      onSelect({id: value, name: value})
      this.resetInput()
      return
    }

    if (filter) filter(event)
  }

  select = choice => {
    this.props.onSelect(choice)
    this.resetInput()
  }

  remove = tag => event => {
    this.props.onRemove(tag)
    event.preventDefault()
  }

  focus = () => {
    this.refs.input.focus()
  }

  handleChange = debounce(value => {
    this.props.handleInput(value)
  }, 200)

  render () {
    let { choices, tags, placeholder, className } = this.props
    if (!tags) tags = []
    if (!placeholder) placeholder = 'Type...'

    return

        {tags.map(t =>

          {t.avatar_url && <NonLinkAvatar person={t}/>}
          {t.label || t.name}
          ×

)}

      <input ref='input' type='text' placeholder={placeholder} spellCheck={false}
        onChange={event => this.handleChange(event.target.value)}
        onKeyDown={this.handleKeys}/>

      {!isEmpty(choices) &&

        <KeyControlledItemList className='dropdown-menu' ref='list' items={choices} onChange={this.select}/>

}

  }
}
<|endoftext|>


<commit_before>( function( window, define, require, undefined ) {

    require.config( {
        enforceDefine: false,
        optimize: 'uglify2',
        waitSeconds: 0,
        catchError: {
            define: true
        },

        paths: {

            // Config will be switched on build
            config:             'config/development',

            // App
            vendor:             'vendor',
            utils:              'utils',

            // Components
            components:         '../',
            modules:            '../modules',
            pattern:            '../pattern',
            site:               '../site',

            // Plugins
            load:               'vendor/plugins/load',
            text:               'vendor/plugins/text',

            // Libraries
            lodash:             'vendor/lodash.build',

            // If it is not necessary to support IE8 its recommended to
            // use jQuery 2.X.X
            //jquery:         '../vendor/jquery-2.1.3'

            // For IE8 support use jquery 1.11.X
            jquery:             'vendor/jquery-1.11.3'

        },

        shim: {
            jquery: {
                exports:        '$'
            }
        },

        // Example for a module package
        packages: [
            {
                // This module can now be required by "modules/test-module"
                // instead of "modules/test-module/test-module"
                name: 'modules/test-module',
                main: 'test-module'
            }
        ]
    } );

    define( [
        'lodash',
        'utils/core'
    ], function( _, App ) {

        // Scope for load plugin
        require.config( {
            globalScope: App
        } );

        require( [
            'config'
            // Extend with global dependencies
        ], function( config ) {

            if ( config.dev ) {

                // Allow access to App object via global scope in dev mode
                window.App = App;
            }

            App.init();

        } );
    } );

}( this, this.define, this.require ) );
<commit_msg>Fix typo in requirejs paths<commit_after>( function( window, define, require, undefined ) {

    require.config( {
        enforceDefine: false,
        optimize: 'uglify2',
        waitSeconds: 0,
        catchError: {
            define: true
        },

        paths: {

            // Config will be switched on build
            config:             'config/development',

            // App
            vendor:             'vendor',
            utils:              'utils',

            // Components
            components:         '../',
            modules:            '../modules',
            patterns:            '../patterns',
            site:               '../site',

            // Plugins
            load:               'vendor/plugins/load',
            text:               'vendor/plugins/text',

            // Libraries
            lodash:             'vendor/lodash.build',

            // If it is not necessary to support IE8 its recommended to
            // use jQuery 2.X.X
            //jquery:         '../vendor/jquery-2.1.3'

            // For IE8 support use jquery 1.11.X
            jquery:             'vendor/jquery-1.11.3'

        },

        shim: {
            jquery: {
                exports:        '$'
            }
        },

        // Example for a module package
        packages: [
            {
                // This module can now be required by "modules/test-module"
                // instead of "modules/test-module/test-module"
                name: 'modules/test-module',
                main: 'test-module'
            }
        ]
    } );

    define( [
        'lodash',
        'utils/core'
    ], function( _, App ) {

        // Scope for load plugin
        require.config( {
            globalScope: App
        } );

        require( [
            'config'
            // Extend with global dependencies
        ], function( config ) {

            if ( config.dev ) {

                // Allow access to App object via global scope in dev mode
                window.App = App;
            }

            App.init();

        } );
    } );

}( this, this.define, this.require ) );
<|endoftext|>


<commit_before>module.exports = function(app) {
  app.config([
    'formioComponentsProvider',
    function(formioComponentsProvider) {
      formioComponentsProvider.register('datagrid', {
        fbtemplate: 'formio/formbuilder/datagrid.html',
        icon: 'fa fa-list',
        views: [
          {
            name: 'Display',
            template: 'formio/components/datagrid/display.html'
          },
          {
            name: 'API',
            template: 'formio/components/common/api.html'
          },
          {
            name: 'Conditional',
            template: 'formio/components/common/conditional.html'
          }
        ],
        documentation: 'http://help.form.io/userguide/#datagrid',
        noDndOverlay: true,
        confirmRemove: true
      });
    }
  ]);

  app.run([
    '$templateCache',
    function($templateCache) {
      $templateCache.put('formio/components/datagrid/display.html',
        '<ng-form>' +
        '<form-builder-option property="label"></form-builder-option>' +
        '<form-builder-option property="addAnother"></form-builder-option>' +
        '<form-builder-option property="customClass"></form-builder-option>' +
        '<form-builder-option property="customClass"></form-builder-option>' +
        '<form-builder-option property="striped"></form-builder-option>' +
        '<form-builder-option property="bordered"></form-builder-option>' +
        '<form-builder-option property="hover"></form-builder-option>' +
        '<form-builder-option property="condensed"></form-builder-option>' +
        '<form-builder-option property="protected"></form-builder-option>' +
        '<form-builder-option property="persistent"></form-builder-option>' +
        '<form-builder-option property="tableView"></form-builder-option>' +
        '</ng-form>'
      );

      $templateCache.put('formio/formbuilder/datagrid.html',
        '<form-builder-row class="formio-row" component="component" form="form" formio="formio"></form-builder-row>'
      );
    }
  ]);
};
<commit_msg>FA-795 - Removing duplicate css configuration.<commit_after>module.exports = function(app) {
  app.config([
    'formioComponentsProvider',
    function(formioComponentsProvider) {
      formioComponentsProvider.register('datagrid', {
        fbtemplate: 'formio/formbuilder/datagrid.html',
        icon: 'fa fa-list',
        views: [
          {
            name: 'Display',
            template: 'formio/components/datagrid/display.html'
          },
          {
            name: 'API',
            template: 'formio/components/common/api.html'
          },
          {
            name: 'Conditional',
            template: 'formio/components/common/conditional.html'
          }
        ],
        documentation: 'http://help.form.io/userguide/#datagrid',
        noDndOverlay: true,
        confirmRemove: true
      });
    }
  ]);

  app.run([
    '$templateCache',
    function($templateCache) {
      $templateCache.put('formio/components/datagrid/display.html',
        '<ng-form>' +
        '<form-builder-option property="label"></form-builder-option>' +
        '<form-builder-option property="addAnother"></form-builder-option>' +
        '<form-builder-option property="customClass"></form-builder-option>' +
        '<form-builder-option property="striped"></form-builder-option>' +
        '<form-builder-option property="bordered"></form-builder-option>' +
        '<form-builder-option property="hover"></form-builder-option>' +
        '<form-builder-option property="condensed"></form-builder-option>' +
        '<form-builder-option property="protected"></form-builder-option>' +
        '<form-builder-option property="persistent"></form-builder-option>' +
        '<form-builder-option property="tableView"></form-builder-option>' +
        '</ng-form>'
      );

      $templateCache.put('formio/formbuilder/datagrid.html',
        '<form-builder-row class="formio-row" component="component" form="form" formio="formio"></form-builder-row>'
      );
    }
  ]);
};
<|endoftext|>


<commit_before>'use strict';
// Result comparison tests to be run by NodeJS/JSDOM test runner
var jsonTests = {
  reviews: retrieveReviews
};

if (typeof init === 'undefined')
  var init = false;

// For execution in browser
if (typeof chrome !== 'undefined' && !init)
  setupExtensionEvents();

function setupExtensionEvents() {
  chrome.runtime.onMessage.addListener(request => {
    if (request.action == 'retrieve') {
      if (!loggedIn()) {
        chrome.runtime.sendMessage({
          action: 'notice-login'
        });
        return false;
      }
      if (window.location.protocol == 'http:') {
        plugin.reportError('Please visit the HTTPS version of Amazon.com.');
        init = false;
        return false;
      }
      let datasets = {};
      datasets.schemaKey = request.schema.schema.key;
      datasets.schemaVersion = request.schema.schema.version;
      retrieveReviews(reviews => {
        datasets.reviews = new DataSet(reviews, request.schema.reviews).set;
        chrome.runtime.sendMessage({
          action: 'dispatch',
          data: datasets,
          schema: request.schema
        });
      });
    }
  });
  // Prevent repeated initialization
  init = true;
}

function loggedIn() {
  return !Boolean($('#nav-flyout-ya-signin').length);
}

function retrieveReviews(callback) {
  let reviews = {
    head: {},
    data: []
  };
  let pages = [1];
  let profileURL = 'https://www.amazon.com/gp/profile/';

  plugin.report('Fetching your profile info …');
  // We use XMLHttpRequest here because jQuery does not expose responseURL,
  // due to limited support for it; see https://bugs.jquery.com/ticket/15173
  let req = new XMLHttpRequest();
  req.addEventListener('load', processProfile);
  req.addEventListener('error', plugin.handleConnectionError(profileURL));
  req.open('GET', profileURL);
  req.send();

  function processProfile() {
    try {
      let $dom = $($.parseHTML(this.responseText));
      reviews.head.reviewerName = $dom.find('.public-name-text').text();

      // The requests redirects to the full profile URL
      reviews.head.reviewerURL = this.responseURL;
      let firstURL = 'https://www.amazon.com/gp/cdp/member-reviews/';
      plugin.report('Fetching page 1 …');
      $.get(firstURL)
        .done(processPage)
        .fail(plugin.handleConnectionError(firstURL));
    } catch (error) {
      plugin.reportError('An error occurred processing your user profile.', error.stack);
    }

  }

  function processPage(html) {
    try {
      let $dom = $($.parseHTML(html));
      let reviewElements = $dom.find('table[cellpadding="0"][cellspacing="0"] tr').has('div.reviewText');
      reviewElements.each((i, reviewElement) => {
        let product, productURL, headline, date, text, starRating;
        let $reviewElement = $(reviewElement);

        let productLink = $reviewElement.prev().find('b a');
        product = $(productLink).text();

        productURL = $(productLink).attr('href');
        productURL = normalizeURL(productURL);
        headline = $reviewElement.find('td b').first().text();
        text = $reviewElement.find('.reviewText').first().html();
        date = $reviewElement.find('td nobr').first().text();
        date = plugin.getISODate(date);

        // We ignore decimals, although the number is exressed as "3.0" etc.
        // this seems to be only used for averages
        starRating = (($reviewElement
            .find('div img[width="64"]')
            .attr('alt') || '')
          .match(/^\d/) || [])[0];

        let reviewObj = {
          product,
          productURL,
          headline,
          date,
          text,
          starRating
        };
        reviews.data.push(reviewObj);
      });

      // There's no "Next / Prev", so we grab the rightmost link in the page nav
      // and make sure it's not a page we've seen before
      let nextPageLink = $dom.find('div[align="right"] b a').last();
      let nextPage = Number(nextPageLink.text());

      if (nextPage && pages.indexOf(nextPage) == -1) {
        let progress = `Fetching page ${nextPage} …`;
        plugin.report(progress);
        pages.push(nextPage);
        let nextPageURL = 'https://www.amazon.com' + nextPageLink.attr('href');
        $.get(nextPageURL)
          .done(processPage)
          .fail(plugin.handleConnectionError(nextPageURL));
      } else {
        callback(reviews);
      }
    } catch (error) {
      plugin.reportError(`An error occurred processing your reviews.`, error.stack);
    }
    // We normalize URLs by stripping the referral string
    function normalizeURL(url) {
      if (/\/ref=.*/.test(url)) {
        url = url.match(/(.*\/)(ref=.*)?/)[1];
      }
      return url;
    }
  }
}
<commit_msg>Fix pagination logic<commit_after>'use strict';
// Result comparison tests to be run by NodeJS/JSDOM test runner
var jsonTests = {
  reviews: retrieveReviews
};

if (typeof init === 'undefined')
  var init = false;

// For execution in browser
if (typeof chrome !== 'undefined' && !init)
  setupExtensionEvents();

function setupExtensionEvents() {
  chrome.runtime.onMessage.addListener(request => {
    if (request.action == 'retrieve') {
      if (!loggedIn()) {
        chrome.runtime.sendMessage({
          action: 'notice-login'
        });
        return false;
      }
      if (window.location.protocol == 'http:') {
        plugin.reportError('Please visit the HTTPS version of Amazon.com.');
        init = false;
        return false;
      }
      let datasets = {};
      datasets.schemaKey = request.schema.schema.key;
      datasets.schemaVersion = request.schema.schema.version;
      retrieveReviews(reviews => {
        datasets.reviews = new DataSet(reviews, request.schema.reviews).set;
        chrome.runtime.sendMessage({
          action: 'dispatch',
          data: datasets,
          schema: request.schema
        });
      });
    }
  });
  // Prevent repeated initialization
  init = true;
}

function loggedIn() {
  return !Boolean($('#nav-flyout-ya-signin').length);
}

function retrieveReviews(callback) {
  let reviews = {
    head: {},
    data: []
  };
  let currentPage = 0;
  let profileURL = 'https://www.amazon.com/gp/profile/';

  plugin.report('Fetching your profile info …');
  // We use XMLHttpRequest here because jQuery does not expose responseURL,
  // due to limited support for it; see https://bugs.jquery.com/ticket/15173
  let req = new XMLHttpRequest();
  req.addEventListener('load', processProfile);
  req.addEventListener('error', plugin.handleConnectionError(profileURL));
  req.open('GET', profileURL);
  req.send();

  function processProfile() {
    try {
      let $dom = $($.parseHTML(this.responseText));
      reviews.head.reviewerName = $dom.find('.public-name-text').text();

      // The requests redirects to the full profile URL
      reviews.head.reviewerURL = this.responseURL;
      let firstURL = 'https://www.amazon.com/gp/cdp/member-reviews/';
      plugin.report('Fetching page 1 …');
      $.get(firstURL)
        .done(processPage)
        .fail(plugin.handleConnectionError(firstURL));
    } catch (error) {
      plugin.reportError('An error occurred processing your user profile.', error.stack);
    }

  }

  function processPage(html) {
    try {
      currentPage++;

      let $dom = $($.parseHTML(html));
      let reviewElements = $dom.find('table[cellpadding="0"][cellspacing="0"] tr').has('div.reviewText');
      reviewElements.each((i, reviewElement) => {
        let product, productURL, headline, date, text, starRating;
        let $reviewElement = $(reviewElement);

        let productLink = $reviewElement.prev().find('b a');
        product = $(productLink).text();

        productURL = $(productLink).attr('href');
        productURL = normalizeURL(productURL);
        headline = $reviewElement.find('td b').first().text();
        text = $reviewElement.find('.reviewText').first().html();
        date = $reviewElement.find('td nobr').first().text();
        date = plugin.getISODate(date);

        // We ignore decimals, although the number is exressed as "3.0" etc.
        // this seems to be only used for averages
        starRating = (($reviewElement
            .find('div img[width="64"]')
            .attr('alt') || '')
          .match(/^\d/) || [])[0];

        let reviewObj = {
          product,
          productURL,
          headline,
          date,
          text,
          starRating
        };
        reviews.data.push(reviewObj);
      });

      let nextPage = currentPage + 1;

      // The pagination is just a set of numbered links, so if we're on page
      // "4", we try to find one that's labeled "5", or "5-" since the last link
      // always is labeled with a range (11-20, 21-30, etc.).
      let regEx = new RegExp('^' + String(nextPage) + '(-\\d*$|$)');

      let $pageMatches = $dom
        .find('td div[align="right"] b a')
        .filter(function() {
          return regEx.test($(this).text());
        });

      if ($pageMatches.length) {
        let nextPageURL = $pageMatches.attr('href');
        let progress = `Fetching page ${nextPage} …`;
        plugin.report(progress);
        $.get(nextPageURL)
          .done(processPage)
          .fail(plugin.handleConnectionError(nextPageURL));
      } else {
        callback(reviews);
      }
    } catch (error) {
      plugin.reportError(`An error occurred processing your reviews.`, error.stack);
    }
    // We normalize URLs by stripping the referral string
    function normalizeURL(url) {
      if (/\/ref=.*/.test(url)) {
        url = url.match(/(.*\/)(ref=.*)?/)[1];
      }
      return url;
    }
  }
}
<|endoftext|>


<commit_before>beers = [
  {
    "name": "Belgian Tripel",
    "shortName": "BT",
    "done": false,
    "gone": false,
    "state": "Fermenting",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/19\/2015",
        "end": "01\/19\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/20\/2015",
        "end": "02\/13\/2015"
      },
      {
        "name": "Conditioning",
        "start": "02\/14\/2015",
        "end": "03\/07\/2015"
      }
    ]
  },
  {
    "name": "IPA",
    "shortName": "IPA",
    "done": false,
    "gone": false,
    "state": "Bottled and Conditioning",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/19\/2015",
        "end": "01\/19\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/20\/2015",
        "end": "01\/25\/2015"
      },
      {
        "name": "Dry Hop",
        "start": "01\/26\/2015",
        "end": "01\/26\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/27\/2015",
        "end": "02\/06\/2015"
      },
      {
        "name": "Conditioning",
        "start": "02\/07\/2015",
        "end": "02\/20\/2015"
      }
    ]
  },
  {
    "name": "Watch Your Tongue Ginger Beer",
    "shortName": "GB",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/06\/2015",
        "end": "01\/06\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/07\/2015",
        "end": "01\/10\/2015"
      },
      {
        "name": "\"Cold Crash\"",
        "start": "01\/11\/2015",
        "end": "01\/18\/2015"
      },
      {
        "name": "Conditioning",
        "start": "01\/19\/2015",
        "end": "01\/20\/2015"
      }
    ]
  },
  {
    "name": "Winter Break Red",
    "shortName": "WBR",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "12\/17\/2014",
        "end": "12\/17\/2014"
      },
      {
        "name": "Fermentation",
        "start": "12\/18\/2014",
        "end": "01\/06\/2015"
      },
      {
        "name": "Conditioning",
        "start": "01\/07\/2015",
        "end": "01\/16\/2015"
      }
    ]
  },
  {
    "name": "Responsible Red",
    "shortName": "RR",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "11\/16\/2014",
        "end": "11\/16\/2014"
      },
      {
        "name": "Fermentation",
        "start": "11\/17\/2014",
        "end": "11\/30\/2014"
      },
      {
        "name": "Conditioning",
        "start": "12\/01\/2014",
        "end": "12\/14\/2014"
      }
    ]
  }
]
<commit_msg>Testing real quick<commit_after>beers = [
  {
    "name": "Belgian Tripel",
    "shortName": "BT",
    "done": true,
    "gone": false,
    "state": "Fermenting",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/19\/2015",
        "end": "01\/19\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/20\/2015",
        "end": "02\/13\/2015"
      },
      {
        "name": "Conditioning",
        "start": "02\/14\/2015",
        "end": "03\/07\/2015"
      }
    ]
  },
  {
    "name": "IPA",
    "shortName": "IPA",
    "done": false,
    "gone": false,
    "state": "Bottled and Conditioning",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/19\/2015",
        "end": "01\/19\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/20\/2015",
        "end": "01\/25\/2015"
      },
      {
        "name": "Dry Hop",
        "start": "01\/26\/2015",
        "end": "01\/26\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/27\/2015",
        "end": "02\/06\/2015"
      },
      {
        "name": "Conditioning",
        "start": "02\/07\/2015",
        "end": "02\/20\/2015"
      }
    ]
  },
  {
    "name": "Watch Your Tongue Ginger Beer",
    "shortName": "GB",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "01\/06\/2015",
        "end": "01\/06\/2015"
      },
      {
        "name": "Fermentation",
        "start": "01\/07\/2015",
        "end": "01\/10\/2015"
      },
      {
        "name": "\"Cold Crash\"",
        "start": "01\/11\/2015",
        "end": "01\/18\/2015"
      },
      {
        "name": "Conditioning",
        "start": "01\/19\/2015",
        "end": "01\/20\/2015"
      }
    ]
  },
  {
    "name": "Winter Break Red",
    "shortName": "WBR",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "12\/17\/2014",
        "end": "12\/17\/2014"
      },
      {
        "name": "Fermentation",
        "start": "12\/18\/2014",
        "end": "01\/06\/2015"
      },
      {
        "name": "Conditioning",
        "start": "01\/07\/2015",
        "end": "01\/16\/2015"
      }
    ]
  },
  {
    "name": "Responsible Red",
    "shortName": "RR",
    "done": true,
    "gone": true,
    "state": "All gone!",
    "steps": [
      {
        "name": "Brew Day",
        "start": "11\/16\/2014",
        "end": "11\/16\/2014"
      },
      {
        "name": "Fermentation",
        "start": "11\/17\/2014",
        "end": "11\/30\/2014"
      },
      {
        "name": "Conditioning",
        "start": "12\/01\/2014",
        "end": "12\/14\/2014"
      }
    ]
  }
]
<|endoftext|>


<commit_before>const refreshDropdown      = require('@binary-com/binary-style').selectDropdown;
const BinaryPjax           = require('../../base/binary_pjax');
const Client               = require('../../base/client');
const BinarySocket         = require('../../base/socket');
const getDecimalPlaces     = require('../../common/currency').getDecimalPlaces;
const getPaWithdrawalLimit = require('../../common/currency').getPaWithdrawalLimit;
const FormManager          = require('../../common/form_manager');
const validEmailToken      = require('../../common/form_validation').validEmailToken;
const handleVerifyCode     = require('../../common/verification_code').handleVerifyCode;
const localize             = require('../../../_common/localize').localize;
const Url                  = require('../../../_common/url');
const isBinaryApp          = require('../../../config').isBinaryApp;

const PaymentAgentWithdraw = (() => {
    const view_ids  = {
        error  : '#viewError',
        notice : '#viewNotice',
        success: '#viewSuccess',
        confirm: '#viewConfirm',
        form   : '#viewForm',
    };
    const field_ids = {
        ddl_agents: '#ddlAgents',
        txt_agents: '#txtAgents',
        txt_amount: '#txtAmount',
        txt_desc  : '#txtDescription',
    };

    let $agent_error,
        $ddl_agents,
        $txt_agents,
        $views,
        agent_name,
        currency,
        token;

    // -----------------------
    // ----- Agents List -----
    // -----------------------
    const populateAgentsList = (response) => {
        $ddl_agents = $(field_ids.ddl_agents);
        $ddl_agents.empty();
        const pa_list = (response.paymentagent_list || {}).list;
        if (pa_list.length > 0) {
            checkToken(pa_list);
        } else {
            showPageError(localize('Payment Agent services are not available in your country or in your preferred currency.'));
        }
    };

    const checkToken = (pa_list) => {
        token = token || Url.getHashValue('token');
        if (!token) {
            BinarySocket.send({ verify_email: Client.get('email'), type: 'paymentagent_withdraw' });
            if (isBinaryApp()) {
                handleVerifyCode((verification_code) => {
                    token = verification_code;
                    checkToken($ddl_agents, pa_list);
                });
            } else {
                setActiveView(view_ids.notice);
            }
        } else if (!validEmailToken(token)) {
            showPageError('token_error');
        } else {
            insertListOption($ddl_agents, localize('Select payment agent'), '');
            for (let i = 0; i < pa_list.length; i++) {
                insertListOption($ddl_agents, pa_list[i].name, pa_list[i].paymentagent_loginid);
            }
            setActiveView(view_ids.form);

            const form_id = `#${$(view_ids.form).find('form').attr('id')}`;
            const $form   = $(form_id);

            const getAPILimit = limit => {
                const selected_val = getPALoginID();
                if (selected_val){
                    const selected_pa = pa_list.find(pa => pa.paymentagent_loginid === selected_val);
                    if (selected_pa) return selected_pa[`${limit}_withdrawal`];
                }
                return getPaWithdrawalLimit(currency, limit);
            };

            const min  = () => getAPILimit('min');
            const max  = () => getAPILimit('max');

            $agent_error = $('.row-agent').find('.error-msg');
            $txt_agents  = $(field_ids.txt_agents);

            $form.find('.wrapper-row-agent').find('label').append($('', { text: '*', class: 'required_field_asterisk' }));
            $form.find('label[for="txtAmount"]').text(`${localize('Amount in')} ${currency}`);
            trimDescriptionContent();
            FormManager.init(form_id, [
                { selector: field_ids.txt_amount,         validations: ['req', ['number', { type: 'float', decimals: getDecimalPlaces(currency), min, max }], ['custom', { func: () => +Client.get('balance') >= +$(field_ids.txt_amount).val(), message: localize('Insufficient balance.') }]], request_field: 'amount' },
                { selector: field_ids.txt_desc,           validations: ['general'], request_field: 'description' },

                { request_field: 'currency',              value: currency },
                { request_field: 'paymentagent_loginid',  value: getPALoginID },
                { request_field: 'paymentagent_withdraw', value: 1 },
                { request_field: 'dry_run',               value: 1 },
            ], true);

            $ddl_agents.on('change', () => {
                $agent_error.setVisibility(0);
                if ($txt_agents.val()) {
                    $txt_agents.val('');
                }
                if (!$ddl_agents.val()) {
                    // error handling
                    $agent_error.setVisibility(1);
                }
            });

            $txt_agents.on('keyup', () => {
                $agent_error.setVisibility(0);
                if ($ddl_agents.val()) {
                    $ddl_agents.val('');
                    refreshDropdown(field_ids.ddl_agents);
                }
                if (!$txt_agents.val()) {
                    // error handling
                    $agent_error.setVisibility(1);
                }
            });

            FormManager.handleSubmit({
                form_selector       : form_id,
                fnc_response_handler: withdrawResponse,
                fnc_additional_check: checkAgent,
                enable_button       : true,
            });
        }
    };

    const getPALoginID = () => (
        $ddl_agents.val() || $txt_agents.val()
    );

    // Remove multiline and excess whitespaces from description text.
    const trimDescriptionContent = () => {
        document.getElementById('txtDescription').addEventListener('change', e => {
            e.srcElement.value = e.target.value.replace(/\s+/g, ' ');
        });
    };

    const insertListOption = ($ddl_object, item_text, item_value) => {
        $ddl_object.append($('<option/>', { value: item_value, text: item_text }));
    };

    // ----------------------------
    // ----- Withdraw Process -----
    // ----------------------------
    const withdrawResponse = (response) => {
        const request = response.echo_req;
        switch (response.paymentagent_withdraw) {
            case 2: { // dry_run success: showing the confirmation page
                setActiveView(view_ids.confirm);

                $('#lblAgentName').text(agent_name);
                $('#lblCurrency').text(request.currency);
                $('#lblAmount').text(request.amount);

                FormManager.init(view_ids.confirm, [
                    { request_field: 'paymentagent_loginid',  value: request.paymentagent_loginid },
                    { request_field: 'amount',                value: request.amount },
                    { request_field: 'description',           value: request.description },
                    { request_field: 'currency',              value: request.currency },
                    { request_field: 'paymentagent_withdraw', value: 1 },
                ], true);

                FormManager.handleSubmit({
                    form_selector       : view_ids.confirm,
                    fnc_response_handler: withdrawResponse,
                });

                $(`${view_ids.confirm} #btnBack`).click(() => {
                    setActiveView(view_ids.form);
                });
                break;
            }
            case 1: // withdrawal success
                setActiveView(view_ids.success);
                $('#successMessage').css('display', '')
                    .attr('class', 'success-msg')
                    .html($('
', { class: 'checked' }).append($('
', { text: localize('Your request to withdraw [_1] [_2] from your account [_3] to Payment Agent [_4] account has been successfully processed.', [request.currency, request.amount, Client.get('loginid'), agent_name]) })));
                break;

            default: // error
                if (response.echo_req.dry_run === 1) {
                    setActiveView(view_ids.form);
                    $('#withdrawFormMessage').setVisibility(1).html(response.error.message);
                } else if (response.error.code === 'InvalidToken') {
                    showPageError(localize('Your token has expired or is invalid. Please click [_1]here[_2] to restart the verification process.', ['', '']));
                } else {
                    showPageError(response.error.message);
                }
                break;
        }
    };

    // -----------------------------
    // ----- Message Functions -----
    // -----------------------------
    const showPageError = (err_msg, id) => {
        const $error = $(view_ids.error);
        $error.find(' > p').setVisibility(0);
        if (id) {
            $error.find(`#${id}`).setVisibility(1);
        } else {
            $error.find('#custom-error').html(err_msg).setVisibility(1);
        }
        setActiveView(view_ids.error);
    };

    // ----- View Control -----
    const setActiveView = (view_id) => {
        $views.setVisibility(0);
        $(view_id).setVisibility(1);
    };

    const onLoad = () => {
        if (!Client.get('currency')) {
            BinaryPjax.load(`${Url.urlFor('user/set-currency')}`);
            return;
        }
        BinarySocket.wait('get_account_status').then((data) => {
            $views = $('#paymentagent_withdrawal').find('.viewItem');
            $views.setVisibility(0);

            if (/(withdrawal|cashier)_locked/.test(data.get_account_status.status)) {
                showPageError('', 'withdrawal-locked-error');
            } else {
                currency = Client.get('currency');
                if (!currency || +Client.get('balance') === 0) {
                    showPageError(localize('Please [_1]deposit[_2] to your account.', [`<a href='${`${Url.urlFor('cashier/forwardws')}?action=deposit`}'>`, '']));
                    return;
                }
                BinarySocket.send({
                    paymentagent_list: Client.get('residence'),
                    currency,
                })
                    .then(response => populateAgentsList(response));
            }
        });
    };

    const checkAgent = () => {
        if (!$ddl_agents.val() && !$txt_agents.val()) {
            $agent_error.setVisibility(1);
            return false;
        }
        // else
        setAgentName();
        return true;
    };

    const setAgentName = () => {
        agent_name = $ddl_agents.val() ? $ddl_agents.find('option:selected').text() : $txt_agents.val();
    };

    const onUnload = () => {
        token = '';
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = PaymentAgentWithdraw;
<commit_msg>Apply suggestions from code review<commit_after>const refreshDropdown      = require('@binary-com/binary-style').selectDropdown;
const BinaryPjax           = require('../../base/binary_pjax');
const Client               = require('../../base/client');
const BinarySocket         = require('../../base/socket');
const getDecimalPlaces     = require('../../common/currency').getDecimalPlaces;
const getPaWithdrawalLimit = require('../../common/currency').getPaWithdrawalLimit;
const FormManager          = require('../../common/form_manager');
const validEmailToken      = require('../../common/form_validation').validEmailToken;
const handleVerifyCode     = require('../../common/verification_code').handleVerifyCode;
const localize             = require('../../../_common/localize').localize;
const Url                  = require('../../../_common/url');
const isBinaryApp          = require('../../../config').isBinaryApp;

const PaymentAgentWithdraw = (() => {
    const view_ids  = {
        error  : '#viewError',
        notice : '#viewNotice',
        success: '#viewSuccess',
        confirm: '#viewConfirm',
        form   : '#viewForm',
    };
    const field_ids = {
        ddl_agents: '#ddlAgents',
        txt_agents: '#txtAgents',
        txt_amount: '#txtAmount',
        txt_desc  : '#txtDescription',
    };

    let $agent_error,
        $ddl_agents,
        $txt_agents,
        $views,
        agent_name,
        currency,
        token;

    // -----------------------
    // ----- Agents List -----
    // -----------------------
    const populateAgentsList = (response) => {
        $ddl_agents = $(field_ids.ddl_agents);
        $ddl_agents.empty();
        const pa_list = (response.paymentagent_list || {}).list;
        if (pa_list.length > 0) {
            checkToken(pa_list);
        } else {
            showPageError(localize('Payment Agent services are not available in your country or in your preferred currency.'));
        }
    };

    const checkToken = (pa_list) => {
        token = token || Url.getHashValue('token');
        if (!token) {
            BinarySocket.send({ verify_email: Client.get('email'), type: 'paymentagent_withdraw' });
            if (isBinaryApp()) {
                handleVerifyCode((verification_code) => {
                    token = verification_code;
                    checkToken($ddl_agents, pa_list);
                });
            } else {
                setActiveView(view_ids.notice);
            }
        } else if (!validEmailToken(token)) {
            showPageError('token_error');
        } else {
            insertListOption($ddl_agents, localize('Select payment agent'), '');
            for (let i = 0; i < pa_list.length; i++) {
                insertListOption($ddl_agents, pa_list[i].name, pa_list[i].paymentagent_loginid);
            }
            setActiveView(view_ids.form);

            const form_id = `#${$(view_ids.form).find('form').attr('id')}`;
            const $form   = $(form_id);

            const getAPILimit = limit => {
                const selected_val = getPALoginID();
                if (selected_val){
                    const selected_pa = pa_list.find(pa => pa.paymentagent_loginid === selected_val);
                    if (selected_pa) return selected_pa[`${limit}_withdrawal`];
                }
                return getPaWithdrawalLimit(currency, limit);
            };

            const min  = () => getAPILimit('min');
            const max  = () => getAPILimit('max');

            $agent_error = $('.row-agent').find('.error-msg');
            $txt_agents  = $(field_ids.txt_agents);

            $form.find('.wrapper-row-agent').find('label').append($('', { text: '*', class: 'required_field_asterisk' }));
            $form.find('label[for="txtAmount"]').text(`${localize('Amount in')} ${currency}`);
            trimDescriptionContent();
            FormManager.init(form_id, [
                { selector: field_ids.txt_amount, validations: ['req', ['number', { type: 'float', decimals: getDecimalPlaces(currency), min, max }], ['custom', { func: () => +Client.get('balance') >= +$(field_ids.txt_amount).val(), message: localize('Insufficient balance.') }]], request_field: 'amount' },
                { selector: field_ids.txt_desc,   validations: ['general'], request_field: 'description' },

                { request_field: 'currency',              value: currency },
                { request_field: 'paymentagent_loginid',  value: getPALoginID },
                { request_field: 'paymentagent_withdraw', value: 1 },
                { request_field: 'dry_run',               value: 1 },
            ], true);

            $ddl_agents.on('change', () => {
                $agent_error.setVisibility(0);
                if ($txt_agents.val()) {
                    $txt_agents.val('');
                }
                if (!$ddl_agents.val()) {
                    // error handling
                    $agent_error.setVisibility(1);
                }
            });

            $txt_agents.on('keyup', () => {
                $agent_error.setVisibility(0);
                if ($ddl_agents.val()) {
                    $ddl_agents.val('');
                    refreshDropdown(field_ids.ddl_agents);
                }
                if (!$txt_agents.val()) {
                    // error handling
                    $agent_error.setVisibility(1);
                }
            });

            FormManager.handleSubmit({
                form_selector       : form_id,
                fnc_response_handler: withdrawResponse,
                fnc_additional_check: checkAgent,
                enable_button       : true,
            });
        }
    };

    const getPALoginID = () => (
        $ddl_agents.val() || $txt_agents.val()
    );

    // Remove multiline and excess whitespaces from description text.
    const trimDescriptionContent = () => {
        document.getElementById('txtDescription').addEventListener('change', e => {
            e.srcElement.value = e.target.value.replace(/\s+/g, ' ');
        });
    };

    const insertListOption = ($ddl_object, item_text, item_value) => {
        $ddl_object.append($('<option/>', { value: item_value, text: item_text }));
    };

    // ----------------------------
    // ----- Withdraw Process -----
    // ----------------------------
    const withdrawResponse = (response) => {
        const request = response.echo_req;
        switch (response.paymentagent_withdraw) {
            case 2: { // dry_run success: showing the confirmation page
                setActiveView(view_ids.confirm);

                $('#lblAgentName').text(agent_name);
                $('#lblCurrency').text(request.currency);
                $('#lblAmount').text(request.amount);

                FormManager.init(view_ids.confirm, [
                    { request_field: 'paymentagent_loginid',  value: request.paymentagent_loginid },
                    { request_field: 'amount',                value: request.amount },
                    { request_field: 'description',           value: request.description },
                    { request_field: 'currency',              value: request.currency },
                    { request_field: 'paymentagent_withdraw', value: 1 },
                ], true);

                FormManager.handleSubmit({
                    form_selector       : view_ids.confirm,
                    fnc_response_handler: withdrawResponse,
                });

                $(`${view_ids.confirm} #btnBack`).click(() => {
                    setActiveView(view_ids.form);
                });
                break;
            }
            case 1: // withdrawal success
                setActiveView(view_ids.success);
                $('#successMessage').css('display', '')
                    .attr('class', 'success-msg')
                    .html($('
', { class: 'checked' }).append($('
', { text: localize('Your request to withdraw [_1] [_2] from your account [_3] to Payment Agent [_4] account has been successfully processed.', [request.currency, request.amount, Client.get('loginid'), agent_name]) })));
                break;

            default: // error
                if (response.echo_req.dry_run === 1) {
                    setActiveView(view_ids.form);
                    $('#withdrawFormMessage').setVisibility(1).html(response.error.message);
                } else if (response.error.code === 'InvalidToken') {
                    showPageError(localize('Your token has expired or is invalid. Please click [_1]here[_2] to restart the verification process.', ['', '']));
                } else {
                    showPageError(response.error.message);
                }
                break;
        }
    };

    // -----------------------------
    // ----- Message Functions -----
    // -----------------------------
    const showPageError = (err_msg, id) => {
        const $error = $(view_ids.error);
        $error.find(' > p').setVisibility(0);
        if (id) {
            $error.find(`#${id}`).setVisibility(1);
        } else {
            $error.find('#custom-error').html(err_msg).setVisibility(1);
        }
        setActiveView(view_ids.error);
    };

    // ----- View Control -----
    const setActiveView = (view_id) => {
        $views.setVisibility(0);
        $(view_id).setVisibility(1);
    };

    const onLoad = () => {
        if (!Client.get('currency')) {
            BinaryPjax.load(`${Url.urlFor('user/set-currency')}`);
            return;
        }
        BinarySocket.wait('get_account_status').then((data) => {
            $views = $('#paymentagent_withdrawal').find('.viewItem');
            $views.setVisibility(0);

            if (/(withdrawal|cashier)_locked/.test(data.get_account_status.status)) {
                showPageError('', 'withdrawal-locked-error');
            } else {
                currency = Client.get('currency');
                if (!currency || +Client.get('balance') === 0) {
                    showPageError(localize('Please [_1]deposit[_2] to your account.', [`<a href='${`${Url.urlFor('cashier/forwardws')}?action=deposit`}'>`, '']));
                    return;
                }
                BinarySocket.send({
                    paymentagent_list: Client.get('residence'),
                    currency,
                })
                    .then(response => populateAgentsList(response));
            }
        });
    };

    const checkAgent = () => {
        if (!$ddl_agents.val() && !$txt_agents.val()) {
            $agent_error.setVisibility(1);
            return false;
        }
        // else
        setAgentName();
        return true;
    };

    const setAgentName = () => {
        agent_name = $ddl_agents.val() ? $ddl_agents.find('option:selected').text() : $txt_agents.val();
    };

    const onUnload = () => {
        token = '';
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = PaymentAgentWithdraw;
<|endoftext|>