<commit_before>angular.module('yds').directive('ydsRegionSelectorGr', ['Data', '$q',
    function (Data, $q) {
        return {
            restrict: 'E',
            scope: {
                elementH:'@'    // Height of the component in pixels
            },
            templateUrl: ((typeof Drupal != 'undefined')? Drupal.settings.basePath  + Drupal.settings.yds_project.modulePath  +'/' :'') + 'templates/region-selector-gr.html',
            link: function (scope, element) {
                var elementH = parseInt(scope.elementH);

                var regionSelContainer = angular.element(element[0].querySelector('.region-selector-container'));

                //create a random id for the element that will render the plot
                var elementId = "regionsel" + Data.createRandomId();
                regionSelContainer[0].id = elementId;

                //check if the component's height attr is defined, else assign default value
                if(_.isUndefined(elementH) || _.isNaN(elementH))
                    elementH = 300;

                // Selectivity instance
                var selectivity = null;

                // Declare states of map points object, used in the configuration of the map later
                var states = {
                    hover: {
                        color: '#e5ed04'
                    },
                    select: {
                        color: '#a4edba',
                        borderColor: 'black',
                        dashStyle: 'shortdot'
                    }
                };

                // Declare object with regions
                var regions = {
                    "GR.TS": {
                        name: "Thessalia",
                        prefectures: [
                            "N. MAGNISIAS",
                            "N. KARDITSAS",
                            "N. LARISAS",
                            "N. TRIKALON"
                        ]
                    },
                    "GR.AT": {
                        name: "Attiki",
                        prefectures: [
                            "N. PIREOS KE NISON",
                            "N. ANATOLIKIS ATTIKIS",
                            "N. DYTIKIS ATTIKIS",
                            "N. ATHINON"
                        ]
                    },
                    "GR.GC": {
                        name: "Sterea Ellada",
                        prefectures: [
                            "N. VIOTIAS",
                            "N. EVVIAS",
                            "N. EVRYTANIAS",
                            "N. FOKIDAS",
                            "N. FTHIOTIDAS"
                        ]
                    },
                    "GR.MC": {
                        name: "Kentriki Makedonia",
                        prefectures: [
                            "N. IMATHIAS",
                            "N. THESSALONIKIS",
                            "N. KILKIS",
                            "N. PELLAS",
                            "N. PIERIAS",
                            "N. SERRON",
                            "N. CHALKIDIKIS"
                        ]
                    },
                    "GR.CR": {
                        name: "Kriti",
                        prefectures: [
                            "N. CHANION",
                            "N. IRAKLIOU",
                            "N. LASITHIOU",
                            "N. RETHYMNOU"
                        ]
                    },
                    "GR.MT": {
                        name: "Anatoliki Makedonia kai Thraki",
                        prefectures: [
                            "N. DRAMAS",
                            "N. EVROU",
                            "N. KAVALAS",
                            "N. XANTHIS",
                            "N. RODOPIS"
                        ]
                    },
                    "GR.EP": {
                        name: "Ipeiros",
                        prefectures: [
                            "N. ARTAS",
                            "N. IOANNINON",
                            "N. PREVEZAS",
                            "N. THESPROTIAS"
                        ]
                    },
                    "GR.II": {
                        name: "Ionioi Nisoi",
                        prefectures: [
                            "N. KERKYRAS",
                            "N. KEFALLONIAS",
                            "N. LEFKADAS",
                            "N. ZAKYNTHOU"
                        ]
                    },
                    "GR.AN": {
                        name: "Voreio Aigaio",
                        prefectures: [
                            "N. CHIOU",
                            "N. SAMOU",
                            "N. LESVOU"
                        ]
                    },
                    "GR.PP": {
                        name: "Peloponnisos",
                        prefectures: [
                            "N. ARKADIAS",
                            "N. ARGOLIDAS",
                            "N. KORINTHOU",
                            "N. LAKONIAS",
                            "N. MESSINIAS"
                        ]
                    },
                    "GR.AS": {
                        name: "Notio Aigaio",
                        prefectures: [
                            "N. KYKLADON",
                            "N. DODEKANISON"
                        ]
                    },
                    "GR.GW": {
                        name: "Dytiki Ellada",
                        prefectures: [
                            "N. ACHAIAS",
                            "N. ETOLOAKARNANIAS",
                            "N. ILIAS"
                        ]
                    },
                    "GR.MW": {
                        name: "Dytiki Makedonia",
                        prefectures: [
                            "N. FLORINAS",
                            "N. GREVENON",
                            "N. KASTORIAS",
                            "N. KOZANIS"
                        ]
                    },
                    "GR.MA": {
                        name: "Ayion Oros",
                        prefectures: [
                            "AGIO OROS"
                        ]
                    }
                };

                /**
                 * Callback for when drillup happens. Clears the selected points from the chart,
                 * and sets the chart's subtitle to empty
                 */
                var drillup = function () {
                    var chart = this,
                        points = [];
                    setTimeout(function () {
                        points = chart.getSelectedPoints();

                        Highcharts.each(points, function (p) {
                            // unselect points from previous drilldown
                            p.selected = false;
                            p.setState('', true);
                        });
                    }, 0);

                    chart.setTitle(null, {text: ''});
                };

                /**
                 * Callback for when drilldown happens. Gets the drilled-down point, and creates the series that should
                 * be shown based on the drilldownMap
                 * @param e
                 */
                var drilldown = function (e) {
                    if (!e.seriesOptions  && e.point.selected) {
                        var chart = this,
                            mapKey = e.point.drilldown,
                            regionName = e.point.name;
                        chart.showLoading("Loading...");

                        Data.getGeoJSON("high", mapKey).then(function(response) {
                            var mapData = response;
                            var drilldownData = [];

                            // For each prefecture to display, create a value of 1 for it so it is colored
                            $.each(mapData.features, function () {
                                drilldownData.push({
                                    name: this.properties.NAME_ENG,
                                    value: 1
                                });
                            });

                            // Hide loading and add series
                            chart.hideLoading();
                            chart.addSeriesAsDrilldown(e.point, {
                                name: regionName,
                                data: drilldownData,
                                mapData: mapData,
                                joinBy: ['NAME_ENG', "name"],
                                keys: ['NAME_ENG', 'value'],
                                allowPointSelect: true,
                                dataLabels: {
                                    enabled: true,
                                    format: '{point.properties.NAME_ENG}'
                                },
                                tooltip: {
                                    enabled: false,
                                    pointFormatter: function() {
                                        return "" + this.properties.NAME_ENG + "";
                                    }
                                },
                                states: states
                            });
                        });
                    }

                    this.setTitle(null, {text: regionName});
                };

                // Declare object which shows how many prefectures are in each region of Greece
                var drilldownMap = {
                    "GR.TS": 4,
                    "GR.AT": 4,
                    "GR.GC": 5,
                    "GR.MC": 7,
                    "GR.CR": 4,
                    "GR.MT": 5,
                    "GR.EP": 4,
                    "GR.II": 4,
                    "GR.AN": 3,
                    "GR.PP": 5,
                    "GR.AS": 2,
                    "GR.GW": 3,
                    "GR.MW": 4,
                    "GR.MA": 1
                };

                // Get low detail Greece map
                Data.getGeoJSON("low", null).then(function(response) {
                    Highcharts.maps["countries/gr-low-res"] = response;

                    // Get low detail map data
                    var mapData = Highcharts.geojson(Highcharts.maps['countries/gr-low-res']);
                    var data = [];

                    _.each(mapData, function (item) {
                        var code = item.properties.hasc;
                        item.drilldown = code;
                        if (_.has(drilldownMap, code)) {
                            data.push({
                                code: code,
                                value: drilldownMap[code]
                            });
                        } else {
                            data.push({
                                code: code,
                                value: 1
                            });
                            console.warn(code + " does not exist in drilldownMap, something went wrong?");
                        }
                    });

                    new Highcharts.mapChart(elementId, getMapOptions(data, mapData));

                    initializeSelectivity();
                });

                /**
                 * Handles the selection of a region on the Highmaps chart
                 */
                var regionSelectionHandler = function(e) {
                    var clickedPoint = e.target;

                    // Get currently selected vales from Selectivity
                    var selectedValues = $(selectivity).selectivity("data");

                    // Find the name of the clicked point and add it to the selected values
                    var item = regions[clickedPoint.code];  // this object contains a "name" attribute

                    selectedValues.push({
                        id: clickedPoint.code,
                        text: item.name
                    });

                    // Set the new selected data in selectivity (do not trigger change event to prevent loop)
                    $(selectivity).selectivity("data", selectedValues, {
                        triggerChange: false
                    });

                    // Redraw selectivity to show the new selection
                    $(selectivity).selectivity("rerenderSelection");

                    // Redraw the chart to show updated tooltip for the selected point
                    setTimeout(function() {
                        clickedPoint.series.chart.redraw();
                    }, 0);
                };

                /**
                 * Handle the unselection of a region on the Highmaps chart
                 * @param e
                 */
                var regionUnselectionHandler = function(e) {
                    var clickedPoint = e.target;

                    // Get currently selected vales from Selectivity
                    var selectedValues = $(selectivity).selectivity("data");

                    // Remove the clicked point from the selected values
                    selectedValues = _.reject(selectedValues, function(val) {
                        return val.id == clickedPoint.code;
                    });

                    // Set the new selected data in selectivity (do not trigger change event to prevent loop)
                    $(selectivity).selectivity("data", selectedValues, {
                        triggerChange: false
                    });

                    // Redraw selectivity to show the new selection
                    $(selectivity).selectivity("rerenderSelection");
                };

                /**
                 * Create and return the options for the highmaps chart
                 * @param data
                 * @param mapData
                 * @returns {*}
                 */
                var getMapOptions = function(data, mapData) {
                    return {
                        chart: {
                            height: elementH,
                            events: {
                                drilldown: drilldown,
                                drillup: drillup
                            }
                        },
                        legend: { enabled: false },
                        title: {
                            text: 'Greece'
                        },
                        tooltip: {
                            enabled: true,
                            pointFormatter: function() {
                                if (_.has(this, "selected") && this.selected == true) {
                                    return "" + this.name + ": " + this.value +
                                        '
(click again to drilldown)' +
                                        '';
                                } else {
                                    return "" + this.name + ": " + this.value;
                                }
                            }
                        },
                        mapNavigation: {
                            enabled: true,
                            enableMouseWheelZoom: true,
                            enableDoubleClickZoomTo: false,
                            enableDoubleClickZoom: false
                        },
                        colorAxis: {
                            min: 1,
                            type: "logarithmic",
                            minColor: '#FFFFFF',
                            maxColor: '#063798',
                            stops: [
                                [0, '#FFFFFF'],
                                [1, '#063798']
                            ]
                        },
                        series: [{
                            data: data,
                            mapData: mapData,
                            dataLabels: {
                                enabled: true,
                                format: '{point.properties.name}'
                            },
                            joinBy: ['hasc', 'code'],
                            keys: ['hasc', 'value'],
                            name: "Regions of Greece",
                            allowPointSelect: true,
                            states: states,
                            point: {
                                events: {
                                    select: regionSelectionHandler,
                                    unselect: regionUnselectionHandler
                                }
                            }
                        }],
                        drilldown: {
                            activeDataLabelStyle: {
                                color: '#FFFFFF',
                                textDecoration: 'none',
                                textShadow: '0px 1px 3px black'
                            },
                            drillUpButton: {
                                relativeTo: 'spacingBox',
                                position: {
                                    x: 0,
                                    y: 60
                                }
                            }
                        }
                    };
                };

                /**
                 * Get the regions of a country with their prefectures and names, and return them
                 * as an array of items for Selectivity.js
                 * @param regions
                 * @returns {Array}
                 */
                var getSelectivityItemsFromRegions = function(regions) {
                    // Variable to hold the selectivity items
                    var items = [];

                    _.each(regions, function(region, key) {
                        // Add the actual region to the items
                        items.push({
                            id: key,
                            text: region.name
                        });

                        // Add the region's prefectures to the items
                        _.each(region.prefectures, function(pref) {
                            items.push({
                                id: pref,
                                text: pref
                            });
                        });
                    });

                    return items;
                };

                /**
                 * Initialize Selectivity dropdown for region or prefecture selection
                 */
                var initializeSelectivity = function() {
                    // Use jQuery to initialize Selectivity
                    var dropdownContainer = _.first(angular.element(element[0].querySelector('.selectivity-container')));

                    selectivity = $(dropdownContainer).selectivity({
                        items: getSelectivityItemsFromRegions(regions),
                        multiple: true,
                        placeholder: 'Type to search a region or prefecture'
                    });
                };
            }
        };
    }
]);
<commit_msg>Handle selection and unselection of prefectures from Highmap<commit_after>angular.module('yds').directive('ydsRegionSelectorGr', ['Data', '$q',
    function (Data, $q) {
        return {
            restrict: 'E',
            scope: {
                elementH:'@'    // Height of the component in pixels
            },
            templateUrl: ((typeof Drupal != 'undefined')? Drupal.settings.basePath  + Drupal.settings.yds_project.modulePath  +'/' :'') + 'templates/region-selector-gr.html',
            link: function (scope, element) {
                var elementH = parseInt(scope.elementH);

                var regionSelContainer = angular.element(element[0].querySelector('.region-selector-container'));

                //create a random id for the element that will render the plot
                var elementId = "regionsel" + Data.createRandomId();
                regionSelContainer[0].id = elementId;

                //check if the component's height attr is defined, else assign default value
                if(_.isUndefined(elementH) || _.isNaN(elementH))
                    elementH = 300;

                // Selectivity instance
                var selectivity = null;

                // Declare states of map points object, used in the configuration of the map later
                var states = {
                    hover: {
                        color: '#e5ed04'
                    },
                    select: {
                        color: '#a4edba',
                        borderColor: 'black',
                        dashStyle: 'shortdot'
                    }
                };

                // Declare object with regions
                var regions = {
                    "GR.TS": {
                        name: "Thessalia",
                        prefectures: [
                            "N. MAGNISIAS",
                            "N. KARDITSAS",
                            "N. LARISAS",
                            "N. TRIKALON"
                        ]
                    },
                    "GR.AT": {
                        name: "Attiki",
                        prefectures: [
                            "N. PIREOS KE NISON",
                            "N. ANATOLIKIS ATTIKIS",
                            "N. DYTIKIS ATTIKIS",
                            "N. ATHINON"
                        ]
                    },
                    "GR.GC": {
                        name: "Sterea Ellada",
                        prefectures: [
                            "N. VIOTIAS",
                            "N. EVVIAS",
                            "N. EVRYTANIAS",
                            "N. FOKIDAS",
                            "N. FTHIOTIDAS"
                        ]
                    },
                    "GR.MC": {
                        name: "Kentriki Makedonia",
                        prefectures: [
                            "N. IMATHIAS",
                            "N. THESSALONIKIS",
                            "N. KILKIS",
                            "N. PELLAS",
                            "N. PIERIAS",
                            "N. SERRON",
                            "N. CHALKIDIKIS"
                        ]
                    },
                    "GR.CR": {
                        name: "Kriti",
                        prefectures: [
                            "N. CHANION",
                            "N. IRAKLIOU",
                            "N. LASITHIOU",
                            "N. RETHYMNOU"
                        ]
                    },
                    "GR.MT": {
                        name: "Anatoliki Makedonia kai Thraki",
                        prefectures: [
                            "N. DRAMAS",
                            "N. EVROU",
                            "N. KAVALAS",
                            "N. XANTHIS",
                            "N. RODOPIS"
                        ]
                    },
                    "GR.EP": {
                        name: "Ipeiros",
                        prefectures: [
                            "N. ARTAS",
                            "N. IOANNINON",
                            "N. PREVEZAS",
                            "N. THESPROTIAS"
                        ]
                    },
                    "GR.II": {
                        name: "Ionioi Nisoi",
                        prefectures: [
                            "N. KERKYRAS",
                            "N. KEFALLONIAS",
                            "N. LEFKADAS",
                            "N. ZAKYNTHOU"
                        ]
                    },
                    "GR.AN": {
                        name: "Voreio Aigaio",
                        prefectures: [
                            "N. CHIOU",
                            "N. SAMOU",
                            "N. LESVOU"
                        ]
                    },
                    "GR.PP": {
                        name: "Peloponnisos",
                        prefectures: [
                            "N. ARKADIAS",
                            "N. ARGOLIDAS",
                            "N. KORINTHOU",
                            "N. LAKONIAS",
                            "N. MESSINIAS"
                        ]
                    },
                    "GR.AS": {
                        name: "Notio Aigaio",
                        prefectures: [
                            "N. KYKLADON",
                            "N. DODEKANISON"
                        ]
                    },
                    "GR.GW": {
                        name: "Dytiki Ellada",
                        prefectures: [
                            "N. ACHAIAS",
                            "N. ETOLOAKARNANIAS",
                            "N. ILIAS"
                        ]
                    },
                    "GR.MW": {
                        name: "Dytiki Makedonia",
                        prefectures: [
                            "N. FLORINAS",
                            "N. GREVENON",
                            "N. KASTORIAS",
                            "N. KOZANIS"
                        ]
                    },
                    "GR.MA": {
                        name: "Ayion Oros",
                        prefectures: [
                            "AGIO OROS"
                        ]
                    }
                };

                /**
                 * Callback for when drillup happens. Clears the selected points from the chart,
                 * and sets the chart's subtitle to empty
                 */
                var drillup = function () {
                    var chart = this,
                        points = [];
                    setTimeout(function () {
                        points = chart.getSelectedPoints();

                        Highcharts.each(points, function (p) {
                            // unselect points from previous drilldown
                            p.selected = false;
                            p.setState('', true);
                        });
                    }, 0);

                    chart.setTitle(null, {text: ''});
                };

                /**
                 * Callback for when drilldown happens. Gets the drilled-down point, and creates the series that should
                 * be shown based on the drilldownMap
                 * @param e
                 */
                var drilldown = function (e) {
                    if (!e.seriesOptions  && e.point.selected) {
                        var chart = this,
                            mapKey = e.point.drilldown,
                            regionName = e.point.name;
                        chart.showLoading("Loading...");

                        Data.getGeoJSON("high", mapKey).then(function(response) {
                            var mapData = response;
                            var drilldownData = [];

                            // For each prefecture to display, create a value of 1 for it so it is colored
                            $.each(mapData.features, function () {
                                drilldownData.push({
                                    name: this.properties.NAME_ENG,
                                    value: 1
                                });
                            });

                            // Hide loading and add series
                            chart.hideLoading();
                            chart.addSeriesAsDrilldown(e.point, {
                                name: regionName,
                                data: drilldownData,
                                mapData: mapData,
                                joinBy: ['NAME_ENG', "name"],
                                keys: ['NAME_ENG', 'value'],
                                allowPointSelect: true,
                                dataLabels: {
                                    enabled: true,
                                    format: '{point.properties.NAME_ENG}'
                                },
                                tooltip: {
                                    enabled: false,
                                    pointFormatter: function() {
                                        return "" + this.properties.NAME_ENG + "";
                                    }
                                },
                                point: {
                                    events: {
                                        select: prefectureSelectionHandler,
                                        unselect: prefectureUnselectionHandler
                                    }
                                },
                                states: states
                            });
                        });
                    }

                    this.setTitle(null, {text: regionName});
                };

                // Declare object which shows how many prefectures are in each region of Greece
                var drilldownMap = {
                    "GR.TS": 4,
                    "GR.AT": 4,
                    "GR.GC": 5,
                    "GR.MC": 7,
                    "GR.CR": 4,
                    "GR.MT": 5,
                    "GR.EP": 4,
                    "GR.II": 4,
                    "GR.AN": 3,
                    "GR.PP": 5,
                    "GR.AS": 2,
                    "GR.GW": 3,
                    "GR.MW": 4,
                    "GR.MA": 1
                };

                // Get low detail Greece map
                Data.getGeoJSON("low", null).then(function(response) {
                    Highcharts.maps["countries/gr-low-res"] = response;

                    // Get low detail map data
                    var mapData = Highcharts.geojson(Highcharts.maps['countries/gr-low-res']);
                    var data = [];

                    _.each(mapData, function (item) {
                        var code = item.properties.hasc;
                        item.drilldown = code;
                        if (_.has(drilldownMap, code)) {
                            data.push({
                                code: code,
                                value: drilldownMap[code]
                            });
                        } else {
                            data.push({
                                code: code,
                                value: 1
                            });
                            console.warn(code + " does not exist in drilldownMap, something went wrong?");
                        }
                    });

                    new Highcharts.mapChart(elementId, getMapOptions(data, mapData));

                    initializeSelectivity();
                });

                /**
                 * Selection handler for regions and prefectures. Uses the given function to create the new item
                 * to give to selectivity to select
                 * @param e         Highcharts event
                 * @param newItem   Function to create a selectivity item
                 */
                var selectionHandler = function(e, newItem) {
                    var clickedPoint = e.target;

                    // Get currently selected vales from Selectivity
                    var selectedValues = $(selectivity).selectivity("data");

                    // Find the name of the clicked point and add it to the selected values
                    var item = regions[clickedPoint.code];  // this object contains a "name" attribute

                    selectedValues.push(newItem(clickedPoint, item));

                    // Set the new selected data in selectivity (do not trigger change event to prevent loop)
                    $(selectivity).selectivity("data", selectedValues, {
                        triggerChange: false
                    });

                    // Redraw selectivity to show the new selection
                    $(selectivity).selectivity("rerenderSelection");

                    // Redraw the chart to show updated tooltip for the selected point
                    setTimeout(function() {
                        clickedPoint.series.chart.redraw();
                    }, 0);
                };

                /**
                 * Unselection handler for regions and prefectures. Uses the given function to remove the
                 * unselected values from the Selectivity selection
                 * @param e             Highcharts event
                 * @param updateValues  Function that removes the unselected point from a list
                 */
                var unselectionHandler = function(e, updateValues) {
                    var pointToUnselect = e.target;

                    // Get currently selected vales from Selectivity
                    var selectedValues = $(selectivity).selectivity("data");

                    // Remove the clicked point from the selected values
                    selectedValues = updateValues(selectedValues, pointToUnselect);

                    // Set the new selected data in selectivity (do not trigger change event to prevent loop)
                    $(selectivity).selectivity("data", selectedValues, {
                        triggerChange: false
                    });

                    // Redraw selectivity to show the new selection
                    $(selectivity).selectivity("rerenderSelection");
                };

                /**
                 * Handles the selection of a region on the Highmaps chart
                 */
                var regionSelectionHandler = function(e) {
                    selectionHandler(e, function(point, item) {
                        return {
                            id: point.code,
                            text: item.name
                        }
                    });
                };

                /**
                 * Handle the unselection of a region on the Highmaps chart
                 * @param e
                 */
                var regionUnselectionHandler = function(e) {
                    unselectionHandler(e, function(selectedValues, clickedPoint) {
                        return _.reject(selectedValues, function(val) {
                            return val.id == clickedPoint.code;
                        });
                    })
                };

                /**
                 * Handle the selection of a prefecture
                 * @param e
                 */
                var prefectureSelectionHandler = function(e) {
                    selectionHandler(e, function(point, item) {
                        return {
                            id: point.NAME_ENG,
                            text: point.NAME_ENG
                        }
                    });
                };

                /**
                 * Handle the unselection of a prefecture
                 * @param e
                 */
                var prefectureUnselectionHandler = function(e) {
                    unselectionHandler(e, function(selectedValues, pointToUnselect) {
                        return _.reject(selectedValues, function(val) {
                            return val.id == pointToUnselect.NAME_ENG;
                        });
                    });
                };

                /**
                 * Create and return the options for the highmaps chart
                 * @param data
                 * @param mapData
                 * @returns {*}
                 */
                var getMapOptions = function(data, mapData) {
                    return {
                        chart: {
                            height: elementH,
                            events: {
                                drilldown: drilldown,
                                drillup: drillup
                            }
                        },
                        legend: { enabled: false },
                        title: {
                            text: 'Greece'
                        },
                        tooltip: {
                            enabled: true,
                            pointFormatter: function() {
                                if (_.has(this, "selected") && this.selected == true) {
                                    return "" + this.name + ": " + this.value +
                                        '
(click again to drilldown)' +
                                        '';
                                } else {
                                    return "" + this.name + ": " + this.value;
                                }
                            }
                        },
                        mapNavigation: {
                            enabled: true,
                            enableMouseWheelZoom: true,
                            enableDoubleClickZoomTo: false,
                            enableDoubleClickZoom: false
                        },
                        colorAxis: {
                            min: 1,
                            type: "logarithmic",
                            minColor: '#FFFFFF',
                            maxColor: '#063798',
                            stops: [
                                [0, '#FFFFFF'],
                                [1, '#063798']
                            ]
                        },
                        series: [{
                            data: data,
                            mapData: mapData,
                            dataLabels: {
                                enabled: true,
                                format: '{point.properties.name}'
                            },
                            joinBy: ['hasc', 'code'],
                            keys: ['hasc', 'value'],
                            name: "Regions of Greece",
                            allowPointSelect: true,
                            states: states,
                            point: {
                                events: {
                                    select: regionSelectionHandler,
                                    unselect: regionUnselectionHandler
                                }
                            }
                        }],
                        drilldown: {
                            activeDataLabelStyle: {
                                color: '#FFFFFF',
                                textDecoration: 'none',
                                textShadow: '0px 1px 3px black'
                            },
                            drillUpButton: {
                                relativeTo: 'spacingBox',
                                position: {
                                    x: 0,
                                    y: 60
                                }
                            }
                        }
                    };
                };

                /**
                 * Get the regions of a country with their prefectures and names, and return them
                 * as an array of items for Selectivity.js
                 * @param regions
                 * @returns {Array}
                 */
                var getSelectivityItemsFromRegions = function(regions) {
                    // Variable to hold the selectivity items
                    var items = [];

                    _.each(regions, function(region, key) {
                        // Add the actual region to the items
                        items.push({
                            id: key,
                            text: region.name
                        });

                        // Add the region's prefectures to the items
                        _.each(region.prefectures, function(pref) {
                            items.push({
                                id: pref,
                                text: pref
                            });
                        });
                    });

                    return items;
                };

                /**
                 * Initialize Selectivity dropdown for region or prefecture selection
                 */
                var initializeSelectivity = function() {
                    // Use jQuery to initialize Selectivity
                    var dropdownContainer = _.first(angular.element(element[0].querySelector('.selectivity-container')));

                    selectivity = $(dropdownContainer).selectivity({
                        items: getSelectivityItemsFromRegions(regions),
                        multiple: true,
                        placeholder: 'Type to search a region or prefecture'
                    });
                };
            }
        };
    }
]);
<|endoftext|>


<commit_before>define(
  'ephox.echo.api.AriaRegister',

  [
    'ephox.classify.Type',
    'ephox.compass.Arr',
    'ephox.compass.Obj',
    'ephox.echo.api.Styles',
    'ephox.epithet.Id',
    'ephox.highway.Merger',
    'ephox.peanut.Fun',
    'ephox.sugar.api.Attr',
    'ephox.sugar.api.Class',
    'ephox.sugar.api.Element',
    'ephox.sugar.api.Insert',
    'ephox.sugar.api.InsertAll'
  ],

  function (Type, Arr, Obj, Styles, Id, Merger, Fun, Attr, Class, Element, Insert, InsertAll) {
    var helpStyle = Styles.resolve('aria-help');
    var helpVisibleStyle = Styles.resolve('aria-help-visible');

    var roleDocument = function (element) {
      Attr.set(element, 'role', 'document');
    };

    var presentation = function (element) {
    // https://www.w3.org/TR/wai-aria/roles#presentation
      Attr.set(element, 'role', 'presentation');
    };

    var editor = function (container, editor, label, ariaHelp, showHelpHint) {
      // Set role=region: https://www.w3.org/TR/wai-aria/roles#region
      // on editor for better user navigation modes, as it is mostly text content.
      // Better than role=application which constrains the reader navigation
      // - https://www.w3.org/TR/wai-aria/roles#application
      Attr.setAll(container, {
        'role': 'region',
        'aria-label': label
      });

      ariaHelp.each(function (helpText) {
        var aria = Element.fromTag('span');
        presentation(aria);
        Insert.append(aria, Element.fromText(helpText));
        var labelId = Id.generate('ephox-aria');
        Attr.set(aria, 'id', labelId);
        describedBy(editor, labelId);
        Class.add(aria, helpStyle);
        if (showHelpHint === true) Class.add(aria, helpVisibleStyle);
        Insert.append(container, aria);
      });

      // content attributes - surprisingly helps in both classic and inline
      var attrs = {
        'aria-multiline': 'true',
        'aria-label': label,
        title: label
      };

      Attr.setAll(editor, attrs);

      var destroy = function () {
        var removeFromEditor = Fun.curry(Attr.remove, editor);
        Arr.each(Obj.keys(attrs), removeFromEditor);
        removeFromEditor('aria-describedby');
      };

      return {
        destroy: destroy
      };
    };

    // Set the role 'group'
    var group = function (element) {
      Attr.set(element, 'role', 'group');
    };

    // Sets the role 'group', with a label
    var toolbar = function (element, label) {
      Attr.setAll(element, {
        'role': 'group',
        'aria-label': label
      });
    };

    var menu = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'menu'
      });
    };

    var textButton = function (element, contentElement) {
      // Add 'button' roleto a pastry button, and 'presentation' role
      // to the contentElement that contains the button text.
      Attr.set(element, 'role', 'button');
      presentation(contentElement);
    };

    // Set the role 'button'
    var toolbarButton = function (element, label, hasPopup, isToggle) {
      Attr.setAll(element, {
        'role': 'button',
        'aria-label': label,
        'aria-haspopup': '' + hasPopup
      });
      if (isToggle) Attr.set(element, 'aria-pressed', 'false');
      if (hasPopup) Attr.set(element, 'aria-expanded', 'false');
    };

    // Set the role 'toolbar' and aria-label if provided
    var toolbarGroup = function (element, label) {
      // TODO: duplicated from 'ephox.polish.alien.Query', consolidate isEmpty();
      var isEmpty = function (val) {
        // TODO: Move to compass Arr and violin Strings
        return (val === null) || (val === undefined) || (val === '') || (Type.isArray(val) && val.length === 0);
      };
      // End TODO

      Attr.set(element, 'role', 'toolbar');

      // customer groups may have empty label, don't use it
      if (!isEmpty(label)) {
        Attr.set(element, 'aria-label', label);
      }
    };

    var menuItem = function (element, label, hasPopup) {
      var labelTxt = label.map(function (txt) {
        return { 'aria-label': txt };
      }).getOr({});

      Attr.setAll(element, Merger.merge(labelTxt, {
        'role': 'menuitem',
        'aria-haspopup': hasPopup.getOr(false)
      }));
    };

    var menuItemCheckbox = function (element) {
      Attr.setAll(element, {
        'role': 'menuitemcheckbox',
        'aria-checked': false
      });
    };

    var checkbox = function (element, label) {
      Attr.setAll(element, {
        'role': 'checkbox',
        'aria-label': label,
        'aria-checked': false
      });
    };

    var dialog = function (element, label) {
      Attr.setAll(element, {
        'role': 'dialog',
        'aria-label': label
      });
    };

    var button = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'button'
      });
    };

    // return a container object with methods {element, field} containing an html field and label
    var labelledField = function (field, name, labelText) {
      var container = Element.fromTag('div');
      presentation(container);
      var id = name + Id.generate('');
      var label = Element.fromHtml('' + labelText + '');
      Attr.set(label, 'for', id);
      Attr.set(field, 'id', id);
      InsertAll.append(container, [ label, field ]);

      return {
        element: Fun.constant(container),
        field:   Fun.constant(field)
      };
    };

    var textarea = function (element) {
      Attr.setAll(element, {
        'aria-multiline': 'true',
        'role': 'textbox'
      });
    };

    var widget = function (element) {
      Attr.set(element, 'role', 'widget');
    };

    var listBox = function (element) {
      Attr.set(element, 'role', 'listbox');
    };

    var tabList = function (element) {
      Attr.set(element, 'role', 'tablist');
    };

    var tabButton = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'tab'
      });
    };

    var tabPanel = function (element) {
      Attr.setAll(element, {
        'role': 'tabpanel'
      });
    };

    var owns = function (element, id) {
      // https://www.w3.org/TR/wai-aria/states_and_properties#aria-owns
      // Identifies a functional parent/child relationship between dom elements
      // where the DOM hierarchy cannot be used.
      // An element can have only one explicit owner.
      Attr.set(element, 'aria-owns', id);
    };

    var ownsRemove = function (element) {
      // An element can have only one explicit owner, so this removes the attribute.
      Attr.remove(element, 'aria-owns');
    };

    var controls = function (element, id) {
      Attr.set(element, 'aria-controls', id);
    };

    var linkElements = function (master, slave) {
      var id = Id.generate('ephox-aria');
      Attr.set(slave, 'id', id);
      controls(master, id);
    };

    var linkTabToPanel = function (tab, panel) {
      linkElements(tab, panel);
    };

    var describedBy = function (element, id) {
      Attr.set(element, 'aria-describedby', id);
    };

    var labelledBy = function (element, id) {
      Attr.set(element, 'aria-labelledby', id);
    };

    var live = function (element, id, _priority) {
      var priority = _priority ? _priority : 'polite';
      Attr.setAll(element, {
        'aria-live': priority,
        'id': id
      });
    };

    var required = function (element) {
      Attr.set(element, 'aria-required', 'true');
    };

    // TODO: Implement form ARIA support
    // var form = function (element, label) {
    //   throw 'Form ARIA support not implemented yet.';
    // };

    var label = function (element, label) {
      Attr.set(element, 'aria-label', label);
    };

    var option = function (element) {
      Attr.set(element, 'role', 'option');
    };

    // TODO: Implement link ARIA support
    // var link = function (element) {
    //   throw 'Link ARIA support not implemented yet.';
    // };

    // TODO: Implement other ARIA support
    // var other = function () {
    //   throw 'Other ARIA support not implemented yet.';
    // };

    var hidden = function (element, status) {
      // Note: aria-hidden=true says this element and all of its descendents are not percievable
      // https://www.w3.org/TR/wai-aria/states_and_properties#aria-hidden
      if (status) {
        Attr.set(element, 'aria-hidden', status);
      } else {
        Attr.remove(element, 'aria-hidden'); // same as setting aria-hidden:false
      }
    };

    var invalid = function (element, status) {
      if (status === true) {
        Attr.set(element, 'aria-invalid', 'true');
      } else {
        Attr.remove(element, 'aria-invalid');
      }
    };

    return {
      document: roleDocument,
      presentation: presentation,
      controls: controls,
      owns: owns,
      ownsRemove: ownsRemove,
      editor: editor,
      group: group,
      toolbar: toolbar,
      toolbarGroup: toolbarGroup,
      toolbarButton: toolbarButton,
      textButton: textButton,
      menu: menu,
      menuItem: menuItem,
      menuItemCheckbox: menuItemCheckbox,
      checkbox: checkbox,
      dialog: dialog,
      button: button,
      labelledField: labelledField,
      textarea: textarea,
      label: label,
      widget: widget,
      option: option,
      listBox: listBox,
      live: live,
      tabList: tabList,
      tabButton: tabButton,
      tabPanel: tabPanel,
      linkElements: linkElements,
      linkTabToPanel: linkTabToPanel,
      describedBy: describedBy,
      labelledBy: labelledBy,
      required: required,
      hidden: hidden,
      invalid: invalid
    };
  }
);<commit_msg>TBIO-4278: rename method<commit_after>define(
  'ephox.echo.api.AriaRegister',

  [
    'ephox.classify.Type',
    'ephox.compass.Arr',
    'ephox.compass.Obj',
    'ephox.echo.api.Styles',
    'ephox.epithet.Id',
    'ephox.highway.Merger',
    'ephox.peanut.Fun',
    'ephox.sugar.api.Attr',
    'ephox.sugar.api.Class',
    'ephox.sugar.api.Element',
    'ephox.sugar.api.Insert',
    'ephox.sugar.api.InsertAll'
  ],

  function (Type, Arr, Obj, Styles, Id, Merger, Fun, Attr, Class, Element, Insert, InsertAll) {
    var helpStyle = Styles.resolve('aria-help');
    var helpVisibleStyle = Styles.resolve('aria-help-visible');

    var roleDocument = function (element) {
      Attr.set(element, 'role', 'document');
    };

    var presentation = function (element) {
    // https://www.w3.org/TR/wai-aria/roles#presentation
      Attr.set(element, 'role', 'presentation');
    };

    var editor = function (container, editor, label, ariaHelp, showHelpHint) {
      // Set role=region: https://www.w3.org/TR/wai-aria/roles#region
      // on editor for better user navigation modes, as it is mostly text content.
      // Better than role=application which constrains the reader navigation
      // - https://www.w3.org/TR/wai-aria/roles#application
      Attr.setAll(container, {
        'role': 'region',
        'aria-label': label
      });

      ariaHelp.each(function (helpText) {
        var aria = Element.fromTag('span');
        presentation(aria);
        Insert.append(aria, Element.fromText(helpText));
        var labelId = Id.generate('ephox-aria');
        Attr.set(aria, 'id', labelId);
        describedBy(editor, labelId);
        Class.add(aria, helpStyle);
        if (showHelpHint === true) Class.add(aria, helpVisibleStyle);
        Insert.append(container, aria);
      });

      // content attributes - surprisingly helps in both classic and inline
      var attrs = {
        'aria-multiline': 'true',
        'aria-label': label,
        title: label
      };

      Attr.setAll(editor, attrs);

      var destroy = function () {
        var removeFromEditor = Fun.curry(Attr.remove, editor);
        Arr.each(Obj.keys(attrs), removeFromEditor);
        removeFromEditor('aria-describedby');
      };

      return {
        destroy: destroy
      };
    };

    // Set the role 'group'
    var group = function (element) {
      Attr.set(element, 'role', 'group');
    };

    // Sets the role 'group', with a label
    var toolbar = function (element, label) {
      Attr.setAll(element, {
        'role': 'group',
        'aria-label': label
      });
    };

    var menu = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'menu'
      });
    };

    var textButton = function (element, contentElement) {
      // Add 'button' roleto a pastry button, and 'presentation' role
      // to the contentElement that contains the button text.
      Attr.set(element, 'role', 'button');
      presentation(contentElement);
    };

    // Set the role 'button'
    var toolbarButton = function (element, label, hasPopup, isToggle) {
      Attr.setAll(element, {
        'role': 'button',
        'aria-label': label,
        'aria-haspopup': '' + hasPopup
      });
      if (isToggle) Attr.set(element, 'aria-pressed', 'false');
      if (hasPopup) Attr.set(element, 'aria-expanded', 'false');
    };

    // Set the role 'toolbar' and aria-label if provided
    var toolbarGroup = function (element, label) {
      // TODO: duplicated from 'ephox.polish.alien.Query', consolidate isEmpty();
      var isEmpty = function (val) {
        // TODO: Move to compass Arr and violin Strings
        return (val === null) || (val === undefined) || (val === '') || (Type.isArray(val) && val.length === 0);
      };
      // End TODO

      Attr.set(element, 'role', 'toolbar');

      // customer groups may have empty label, don't use it
      if (!isEmpty(label)) {
        Attr.set(element, 'aria-label', label);
      }
    };

    var menuItem = function (element, label, hasPopup) {
      var labelTxt = label.map(function (txt) {
        return { 'aria-label': txt };
      }).getOr({});

      Attr.setAll(element, Merger.merge(labelTxt, {
        'role': 'menuitem',
        'aria-haspopup': hasPopup.getOr(false)
      }));
    };

    var menuItemCheckbox = function (element) {
      Attr.setAll(element, {
        'role': 'menuitemcheckbox',
        'aria-checked': false
      });
    };

    var checkbox = function (element, label) {
      Attr.setAll(element, {
        'role': 'checkbox',
        'aria-label': label,
        'aria-checked': false
      });
    };

    var dialog = function (element, label) {
      Attr.setAll(element, {
        'role': 'dialog',
        'aria-label': label
      });
    };

    var button = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'button'
      });
    };

    // return a container object with methods {element, field} containing an html field and label
    var labelledField = function (field, name, labelText) {
      var container = Element.fromTag('div');
      presentation(container);
      var id = name + Id.generate('');
      var label = Element.fromHtml('' + labelText + '');
      Attr.set(label, 'for', id);
      Attr.set(field, 'id', id);
      InsertAll.append(container, [ label, field ]);

      return {
        element: Fun.constant(container),
        field:   Fun.constant(field)
      };
    };

    var textarea = function (element) {
      Attr.setAll(element, {
        'aria-multiline': 'true',
        'role': 'textbox'
      });
    };

    var widget = function (element) {
      Attr.set(element, 'role', 'widget');
    };

    var listBox = function (element) {
      Attr.set(element, 'role', 'listbox');
    };

    var tabList = function (element) {
      Attr.set(element, 'role', 'tablist');
    };

    var tabButton = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'tab'
      });
    };

    var tabPanel = function (element) {
      Attr.setAll(element, {
        'role': 'tabpanel'
      });
    };

    var owns = function (element, id) {
      // https://www.w3.org/TR/wai-aria/states_and_properties#aria-owns
      // Identifies a functional parent/child relationship between dom elements
      // where the DOM hierarchy cannot be used.
      // An element can have only one explicit owner.
      Attr.set(element, 'aria-owns', id);
    };

    var disown = function (element) {
      // An element can have only one explicit owner, so this removes the attribute.
      Attr.remove(element, 'aria-owns');
    };

    var controls = function (element, id) {
      Attr.set(element, 'aria-controls', id);
    };

    var linkElements = function (master, slave) {
      var id = Id.generate('ephox-aria');
      Attr.set(slave, 'id', id);
      controls(master, id);
    };

    var linkTabToPanel = function (tab, panel) {
      linkElements(tab, panel);
    };

    var describedBy = function (element, id) {
      Attr.set(element, 'aria-describedby', id);
    };

    var labelledBy = function (element, id) {
      Attr.set(element, 'aria-labelledby', id);
    };

    var live = function (element, id, _priority) {
      var priority = _priority ? _priority : 'polite';
      Attr.setAll(element, {
        'aria-live': priority,
        'id': id
      });
    };

    var required = function (element) {
      Attr.set(element, 'aria-required', 'true');
    };

    // TODO: Implement form ARIA support
    // var form = function (element, label) {
    //   throw 'Form ARIA support not implemented yet.';
    // };

    var label = function (element, label) {
      Attr.set(element, 'aria-label', label);
    };

    var option = function (element) {
      Attr.set(element, 'role', 'option');
    };

    // TODO: Implement link ARIA support
    // var link = function (element) {
    //   throw 'Link ARIA support not implemented yet.';
    // };

    // TODO: Implement other ARIA support
    // var other = function () {
    //   throw 'Other ARIA support not implemented yet.';
    // };

    var hidden = function (element, status) {
      // Note: aria-hidden=true says this element and all of its descendents are not percievable
      // https://www.w3.org/TR/wai-aria/states_and_properties#aria-hidden
      if (status) {
        Attr.set(element, 'aria-hidden', status);
      } else {
        Attr.remove(element, 'aria-hidden'); // same as setting aria-hidden:false
      }
    };

    var invalid = function (element, status) {
      if (status === true) {
        Attr.set(element, 'aria-invalid', 'true');
      } else {
        Attr.remove(element, 'aria-invalid');
      }
    };

    return {
      document: roleDocument,
      presentation: presentation,
      controls: controls,
      owns: owns,
      disown: disown,
      editor: editor,
      group: group,
      toolbar: toolbar,
      toolbarGroup: toolbarGroup,
      toolbarButton: toolbarButton,
      textButton: textButton,
      menu: menu,
      menuItem: menuItem,
      menuItemCheckbox: menuItemCheckbox,
      checkbox: checkbox,
      dialog: dialog,
      button: button,
      labelledField: labelledField,
      textarea: textarea,
      label: label,
      widget: widget,
      option: option,
      listBox: listBox,
      live: live,
      tabList: tabList,
      tabButton: tabButton,
      tabPanel: tabPanel,
      linkElements: linkElements,
      linkTabToPanel: linkTabToPanel,
      describedBy: describedBy,
      labelledBy: labelledBy,
      required: required,
      hidden: hidden,
      invalid: invalid
    };
  }
);<|endoftext|>


<commit_before>var xitrum = {
  antiCSRFToken: function() {
    return $("meta[name='csrf-token']").attr("content");
  },

  urlFor: function(actionClassName, params) {
    var find = function() {
      for (var i = 0; i < XITRUM_ROUTES.length; i++) {
        var xs = XITRUM_ROUTES[i];
        if (xs[1] === actionClassName) return xs[0];
      }
      throw "[urlFor] No route for: " + actionClassName;
    };

    var compiledRoute = find();

    var ret = XITRUM_BASE_URL;
    for (var i = 0; i < compiledRoute.length; i++) {
      var xs            = compiledRoute[i];
      var token         = xs[0];
      var isPlaceHolder = xs[1];
      if (isPlaceHolder) {
        var s = params[token];
        if (s) {
          ret += "/" + s;
        } else {
          throw "[urlFor] Missing key: " + token + ", for: " + actionClassName;
        }
      } else {
        ret += "/" + token;
      }
    }

    if (ret.length === 0) {
      return "/";
    } else {
      return ret;
    }
  },

  postback: function(event) {
    var target1 = $(event.target);

    var confirmMsg = target1.attr("data-confirm");
    if (confirmMsg && !confirm(confirmMsg)) return false;

    var action = target1.attr("action");
    var data   = "";

    // data may come from "extra" data
    // http://api.jquery.com/data/
    var extraParams = target1.data("extra");
    if (extraParams) data = extraParams + "&";

    // or come from extra form
    var extraFormSelector = target1.attr("data-extra");
    if (extraFormSelector) {
      var extraForm = $(extraFormSelector);
      if (extraForm && extraForm[0].tagName === "FORM" && extraForm.valid())
        data = data + extraForm.serialize() + "&";
    }

    // or come from this element itself
    if (target1[0].tagName === "FORM") {
       if (!target1.valid()) return false;
       data = data + target1.serialize();
    }

    target1.hide();
    target1.after('');

    $.ajax({
      type: "POST",
      url: action,
      data: data,
      error: function(jqxhr) {
        var contentType = jqxhr.getResponseHeader('Content-Type');
        if (contentType && contentType.indexOf('javascript') != -1) {
          try {
            eval(jqxhr.responseText);
          } catch (err) {
            alert("Could not connect to server or server error.");
          }
        } else {
          alert("Could not connect to server or server error.");
        }
      },
      complete: function() {
        target1.show();
        target1.next().remove();
      }
    });

    var after = target1.attr("data-after");
    if (after) {
      var f = eval('(function() {' + after + '})');
      f();
    }

    return false;
  },

  flash: function(msg) {
    var div =
      '
' +
        'Ｘ' +
        '
' + msg + '
' +
      '
';
    $("#flash").append($(div).hide().fadeIn(1000));
  },

  isScrollAtBottom: function(selector) {
    return ($(selector).scrollTop() + $(selector).height() === $(selector)[0].scrollHeight);
  },

  scrollToBottom: function(selector) {
    $(selector).scrollTop($(selector)[0].scrollHeight);
  },

  appendAndScroll: function(selector, text) {
    var wasScrollAtBottom = this.isScrollAtBottom(selector);
    $(selector).append(text);
    if (wasScrollAtBottom) this.scrollToBottom(selector);
  },

  escapeHtml: function(html) {
    return $('
').text(html).html();
  }
};

$(function() {
  $(document).ajaxSend(function(e, req, options) {
    if (options.type != "GET") {
      options.data += (options.data.length > 0 ? "&" : "") + "csrf-token=" + xitrum.antiCSRFToken();
    }
  });

  $(".flash_close").live("click", function(event) {
    var parent = $(event.target).parent();
    parent.fadeOut(1000, function() { parent.remove() });
  });

  // jQuery Validation plugin only works on forms and the forms must be
  // validated once, before any rules("add", rules) can be called
  //
  // We must iterate manually, $("form").validate() only works for the first
  // form, not all forms when there are multiple form in a page
  $("form").each(function(index, form) { $(form).validate() });

  $("[data-postback]").each(function(index, elem) {
    var eventType = $(elem).attr("data-postback");
    $(elem).bind(eventType, xitrum.postback);
  });
});
<commit_msg>Postback: set contentType to "application/x-www-form-urlencoded; charset=UTF-8" explicitly because sometimes jQuery sets it to "text/plain"<commit_after>var xitrum = {
  antiCSRFToken: function() {
    return $("meta[name='csrf-token']").attr("content");
  },

  urlFor: function(actionClassName, params) {
    var find = function() {
      for (var i = 0; i < XITRUM_ROUTES.length; i++) {
        var xs = XITRUM_ROUTES[i];
        if (xs[1] === actionClassName) return xs[0];
      }
      throw "[urlFor] No route for: " + actionClassName;
    };

    var compiledRoute = find();

    var ret = XITRUM_BASE_URL;
    for (var i = 0; i < compiledRoute.length; i++) {
      var xs            = compiledRoute[i];
      var token         = xs[0];
      var isPlaceHolder = xs[1];
      if (isPlaceHolder) {
        var s = params[token];
        if (s) {
          ret += "/" + s;
        } else {
          throw "[urlFor] Missing key: " + token + ", for: " + actionClassName;
        }
      } else {
        ret += "/" + token;
      }
    }

    if (ret.length === 0) {
      return "/";
    } else {
      return ret;
    }
  },

  postback: function(event) {
    var target1 = $(event.target);

    var confirmMsg = target1.attr("data-confirm");
    if (confirmMsg && !confirm(confirmMsg)) return false;

    var action = target1.attr("action");
    var data   = "";

    // data may come from "extra" data
    // http://api.jquery.com/data/
    var extraParams = target1.data("extra");
    if (extraParams) data = extraParams + "&";

    // or come from extra form
    var extraFormSelector = target1.attr("data-extra");
    if (extraFormSelector) {
      var extraForm = $(extraFormSelector);
      if (extraForm && extraForm[0].tagName === "FORM" && extraForm.valid())
        data = data + extraForm.serialize() + "&";
    }

    // or come from this element itself
    if (target1[0].tagName === "FORM") {
       if (!target1.valid()) return false;
       data = data + target1.serialize();
    }

    target1.hide();
    target1.after('');

    $.ajax({
      type: "POST",
      // Need to set explicitly because sometimes jQuery sets it to "text/plain"
      contentType: "application/x-www-form-urlencoded; charset=UTF-8",
      url: action,
      data: data,
      error: function(jqxhr) {
        var contentType = jqxhr.getResponseHeader('Content-Type');
        if (contentType && contentType.indexOf('javascript') != -1) {
          try {
            eval(jqxhr.responseText);
          } catch (err) {
            alert("Could not connect to server or server error.");
          }
        } else {
          alert("Could not connect to server or server error.");
        }
      },
      complete: function() {
        target1.show();
        target1.next().remove();
      }
    });

    var after = target1.attr("data-after");
    if (after) {
      var f = eval('(function() {' + after + '})');
      f();
    }

    return false;
  },

  flash: function(msg) {
    var div =
      '
' +
        'Ｘ' +
        '
' + msg + '
' +
      '
';
    $("#flash").append($(div).hide().fadeIn(1000));
  },

  isScrollAtBottom: function(selector) {
    return ($(selector).scrollTop() + $(selector).height() === $(selector)[0].scrollHeight);
  },

  scrollToBottom: function(selector) {
    $(selector).scrollTop($(selector)[0].scrollHeight);
  },

  appendAndScroll: function(selector, text) {
    var wasScrollAtBottom = this.isScrollAtBottom(selector);
    $(selector).append(text);
    if (wasScrollAtBottom) this.scrollToBottom(selector);
  },

  escapeHtml: function(html) {
    return $('
').text(html).html();
  }
};

$(function() {
  $(document).ajaxSend(function(e, req, options) {
    if (options.type != "GET") {
      options.data += (options.data.length > 0 ? "&" : "") + "csrf-token=" + xitrum.antiCSRFToken();
    }
  });

  $(".flash_close").live("click", function(event) {
    var parent = $(event.target).parent();
    parent.fadeOut(1000, function() { parent.remove() });
  });

  // jQuery Validation plugin only works on forms and the forms must be
  // validated once, before any rules("add", rules) can be called
  //
  // We must iterate manually, $("form").validate() only works for the first
  // form, not all forms when there are multiple form in a page
  $("form").each(function(index, form) { $(form).validate() });

  $("[data-postback]").each(function(index, elem) {
    var eventType = $(elem).attr("data-postback");
    $(elem).bind(eventType, xitrum.postback);
  });
});
<|endoftext|>


<commit_before>(function(window, document, controller) {
    var resourceJS = [

    ];

    var resourceStyle = [
        'https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/blogspotSearch.css'
    ];

    window.onload = function() {
        //
        var na5centScript = document.getElementsByClassName('ns-blogsearch-script')[0];
        var blogspotURL = na5centScript.getAttribute('data-blogspot-url');
        var languages = na5centScript.getAttribute('data-languages') ? JSON.parse(na5centScript.getAttribute('data-languages')) : {};
        var targetElementId = na5centScript.getAttribute('data-element-id');
        var additionalDictionaries = na5centScript.getAttribute('data-additionalDictionaries') || [];
        var slideSearch = na5centScript.getAttribute('data-slide-search') || false;
        if (slideSearch == 'true') {
            resourceJS.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/slideSearch.js');

            resourceStyle.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/jscrollpane/jscrollpane.css');
            resourceStyle.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/slideSearch.css');
        }

        var html = ['

<input id="na5centSearchInput" placeholder="' + (languages.PLACE_HOLDER || 'search...') + '"/><button id="na5centClearButton">' + (languages.CLEAR || 'clear') + '</button>',
            '
',
            '

',
            '

',
            '

',
            '

'
        ];

        document.getElementById(targetElementId).innerHTML = html.join('');
        document.getElementById(targetElementId).className += 'ns-plugin-slide-search';

        for (var index in resourceStyle) {
            loadStyle(resourceStyle[index]);
        }

        for (var index in resourceJS) {
            loadScript(resourceJS[index], function() {
                if (index == (resourceJS.length - 1)) {
                    if (controller) {
                        controller(blogspotURL, languages, additionalDictionaries, window.jQuery);
                    }
                }
            });
        }
    };

    function getHeadElement() {
        return document.getElementsByTagName('head')[0];
    }

    function loadStyle(styleUrl) {
        var link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('href', styleUrl);

        getHeadElement().appendChild(link);
    }

    function loadScript(jsURL, callback) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.onload = callback;
        script.src = jsURL;
        //script.async = false;

        getHeadElement().appendChild(script);
    }
})(window, document, function(blogspotURL, languages, additionalDictionaries, $) {
    if (!window.Blogger || !$) {
        return;
    }

    Blogger.pullRepositoryFromBlog(blogspotURL, function(repository) {
        var settings = {
            repository: repository, //require
            indexOnFields: ['name'], //require
            maximumIndexKeySize: 5,
            additionalDictionaries: (additionalDictionaries && additionalDictionaries.length > 0) ? additionalDictionaries.split(',') : window.additionalDictionaries
        };

        var indexSearch__ = new IndexSearch(settings);
        //====================================================================================

        var $searchInput = $('#na5centSearchInput');
        var $clearButton = $('#na5centClearButton');
        var $summary = $('#na5centSummary');
        var $suggestions = $('#na5centSuggestions');
        var $repositories = $('#na5centRepositories');
        $('.ns-plugin-search-box').show();

        showResult(repository);
        $searchInput.keyup(function() {
            var keyword = $searchInput.val();
            var result = indexSearch__.search(keyword);

            $summary.text('').hide();
            if (result.getTotalPosition() !== 0) {
                $summary.append((languages.SEARCH || 'search') + ' \'')
                        .append($('').text(indexSearch__.getKeyword()).addClass('summary-highlight'))
                        .append('\' ' + (languages.FOUND || 'found') + ' ')
                        .append($('').text(result.getTotalPosition()).addClass('summary-highlight'))
                        .append(' ' + (languages.POSITIONS || 'positions on') + ' ')
                        .append($('').text(result.getTotalSentence()).addClass('summary-highlight'))
                        .append(' ' + (languages.SENTENCES || 'sentences.'))
                        .show();
            } else if (keyword !== '') {
                $summary.append((languages.SEARCH || 'search') + ' \'')
                        .append($('').text(indexSearch__.getKeyword()).addClass('summary-highlight'))
                        .append('\' ' + (languages.NOT_FOUND || 'not found'))
                        .show();
            }

            $suggestions.text('').hide();
            var suggestions = result.getSuggestions();
            if (suggestions.length !== 0) {
                $suggestions.append((languages.DO_YOU_MEAN || 'do you mean') + ' ');
                for (var suggestIndex in suggestions) {
                    var suggest = suggestions[suggestIndex];
                    var highlight = suggest.highlight;

                    if (suggestIndex != 0) {
                        $suggestions.append(', ');
                    }

                    var $suggestItem = $('').attr('href', '#' + suggest.word)
                            .attr('data-suggest', suggest.word)
                            .html(highlight)
                            .click(function(event) {
                        event.preventDefault();
                        $searchInput.val($(this).attr('data-suggest')).keyup();
                    });

                    $suggestions.append($suggestItem);
                }

                $suggestions.append(' ').append('?').show();
            }

            showResult(result.getContent());
        });

        $clearButton.click(function() {
            $searchInput.val('');
            indexSearch__.clear();
            $summary.text('');
            $suggestions.text('');
            showResult(repository);
        });

        function showResult(rootNode) {
            var $rootDOM = $('
');
            $repositories.html($rootDOM);
            walkRepositoryShowResult(rootNode, $rootDOM);
        }

        function walkRepositoryShowResult(parentNode, $parentDOM) {
            var nodes = parentNode.nodes;
            if (!nodes || nodes.length === 0) {
                return;
            }

            for (var index in nodes) {
                var childNode = nodes[index];
                var $childLink = $('').attr('href', childNode.link).html(childNode.nameHighlight || childNode.name);
                var $newPost = childNode.newPost ? $('').text('New!').addClass('index-search-new-post') : '';
                var $childDOM = $('
');
                var $list = $('
').attr('class', childNode.level)
                        .append($childLink)
                        .append($newPost)
                        .append($childDOM);

                if (childNode.published) {
                    $list.attr('title', dateFormat(childNode.published));
                }

                $parentDOM.append($list);

                walkRepositoryShowResult(childNode, $childDOM);
            }
        }

        function dateFormat(date) {
            return moment(date).format('MMMM Do YYYY, h:mm:ss a');
        }
    });
});
<commit_msg>integrate file<commit_after>(function(window, document, controller) {
    var resourceJS = [
    ];

    var resourceStyle = [
        'https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/blogspotSearch.css'
    ];

    window.onload = function() {
        //
        var na5centScript = document.getElementsByClassName('ns-blogsearch-script')[0];
        var blogspotURL = na5centScript.getAttribute('data-blogspot-url');
        var languages = na5centScript.getAttribute('data-languages') ? JSON.parse(na5centScript.getAttribute('data-languages')) : {};
        var targetElementId = na5centScript.getAttribute('data-element-id');
        var additionalDictionaries = na5centScript.getAttribute('data-additionalDictionaries') || [];
        var slideSearch = na5centScript.getAttribute('data-slide-search') || false;
        if (slideSearch == 'true') {
            resourceJS.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/slideSearch.js');

            resourceStyle.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/jscrollpane/jscrollpane.css');
            resourceStyle.push('https://rawgithub.com/jittagornp/index-search-javascript/master/src/main/webapp/slideSearch.css');
        }

        var html = ['

<input id="na5centSearchInput" placeholder="' + (languages.PLACE_HOLDER || 'search...') + '"/><button id="na5centClearButton">' + (languages.CLEAR || 'clear') + '</button>',
            '
',
            '

',
            '

',
            '

',
            '

'
        ];

        document.getElementById(targetElementId).innerHTML = html.join('');
        document.getElementById(targetElementId).className += 'ns-plugin-slide-search';

        for (var index in resourceStyle) {
            loadStyle(resourceStyle[index]);
        }

        for (var index in resourceJS) {
            loadScript(resourceJS[index], function() {
                if (resourceJS.length > 0) {
                    if (index == (resourceJS.length - 1) && controller) {
                        controller(blogspotURL, languages, additionalDictionaries, window.jQuery);
                    }
                } else {
                    if (controller) {
                        controller(blogspotURL, languages, additionalDictionaries, window.jQuery);
                    }
                }
            });
        }
    };

    function getHeadElement() {
        return document.getElementsByTagName('head')[0];
    }

    function loadStyle(styleUrl) {
        var link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('href', styleUrl);

        getHeadElement().appendChild(link);
    }

    function loadScript(jsURL, callback) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.onload = callback;
        script.src = jsURL;
        //script.async = false;

        getHeadElement().appendChild(script);
    }
})(window, document, function(blogspotURL, languages, additionalDictionaries, $) {
    if (!window.Blogger || !$) {
        return;
    }

    Blogger.pullRepositoryFromBlog(blogspotURL, function(repository) {
        var settings = {
            repository: repository, //require
            indexOnFields: ['name'], //require
            maximumIndexKeySize: 5,
            additionalDictionaries: (additionalDictionaries && additionalDictionaries.length > 0) ? additionalDictionaries.split(',') : window.additionalDictionaries
        };

        var indexSearch__ = new IndexSearch(settings);
        //====================================================================================

        var $searchInput = $('#na5centSearchInput');
        var $clearButton = $('#na5centClearButton');
        var $summary = $('#na5centSummary');
        var $suggestions = $('#na5centSuggestions');
        var $repositories = $('#na5centRepositories');
        $('.ns-plugin-search-box').show();

        showResult(repository);
        $searchInput.keyup(function() {
            var keyword = $searchInput.val();
            var result = indexSearch__.search(keyword);

            $summary.text('').hide();
            if (result.getTotalPosition() !== 0) {
                $summary.append((languages.SEARCH || 'search') + ' \'')
                        .append($('').text(indexSearch__.getKeyword()).addClass('summary-highlight'))
                        .append('\' ' + (languages.FOUND || 'found') + ' ')
                        .append($('').text(result.getTotalPosition()).addClass('summary-highlight'))
                        .append(' ' + (languages.POSITIONS || 'positions on') + ' ')
                        .append($('').text(result.getTotalSentence()).addClass('summary-highlight'))
                        .append(' ' + (languages.SENTENCES || 'sentences.'))
                        .show();
            } else if (keyword !== '') {
                $summary.append((languages.SEARCH || 'search') + ' \'')
                        .append($('').text(indexSearch__.getKeyword()).addClass('summary-highlight'))
                        .append('\' ' + (languages.NOT_FOUND || 'not found'))
                        .show();
            }

            $suggestions.text('').hide();
            var suggestions = result.getSuggestions();
            if (suggestions.length !== 0) {
                $suggestions.append((languages.DO_YOU_MEAN || 'do you mean') + ' ');
                for (var suggestIndex in suggestions) {
                    var suggest = suggestions[suggestIndex];
                    var highlight = suggest.highlight;

                    if (suggestIndex != 0) {
                        $suggestions.append(', ');
                    }

                    var $suggestItem = $('').attr('href', '#' + suggest.word)
                            .attr('data-suggest', suggest.word)
                            .html(highlight)
                            .click(function(event) {
                        event.preventDefault();
                        $searchInput.val($(this).attr('data-suggest')).keyup();
                    });

                    $suggestions.append($suggestItem);
                }

                $suggestions.append(' ').append('?').show();
            }

            showResult(result.getContent());
        });

        $clearButton.click(function() {
            $searchInput.val('');
            indexSearch__.clear();
            $summary.text('');
            $suggestions.text('');
            showResult(repository);
        });

        function showResult(rootNode) {
            var $rootDOM = $('
');
            $repositories.html($rootDOM);
            walkRepositoryShowResult(rootNode, $rootDOM);
        }

        function walkRepositoryShowResult(parentNode, $parentDOM) {
            var nodes = parentNode.nodes;
            if (!nodes || nodes.length === 0) {
                return;
            }

            for (var index in nodes) {
                var childNode = nodes[index];
                var $childLink = $('').attr('href', childNode.link).html(childNode.nameHighlight || childNode.name);
                var $newPost = childNode.newPost ? $('').text('New!').addClass('index-search-new-post') : '';
                var $childDOM = $('
');
                var $list = $('
').attr('class', childNode.level)
                        .append($childLink)
                        .append($newPost)
                        .append($childDOM);

                if (childNode.published) {
                    $list.attr('title', dateFormat(childNode.published));
                }

                $parentDOM.append($list);

                walkRepositoryShowResult(childNode, $childDOM);
            }
        }

        function dateFormat(date) {
            return moment(date).format('MMMM Do YYYY, h:mm:ss a');
        }
    });
});
<|endoftext|>


<commit_before>'use strict';

pinpointApp.controller('SpyCtrl', [ '$scope', '$timeout', '$routeParams', 'NavbarDao', function ($scope, $timeout, $routeParams, NavbarDao) {

    // define private variables
    var oNavbarDao;

    /**
     * initialize
     */
    $timeout(function () {
        oNavbarDao = new NavbarDao();
        if ($routeParams.application) {
            oNavbarDao.setApplication($routeParams.application);
        }
        if ($routeParams.period) {
            oNavbarDao.setPeriod(Number($routeParams.period, 10));
        }
        if ($routeParams.queryEndTime) {
            oNavbarDao.setQueryEndTime(Number($routeParams.queryEndTime, 10));
        }
        $scope.$emit('navbar.initialize', oNavbarDao);
    });

    /**
     * scope event on navbar.changed
     */
    $scope.$on('navbar.changed', function (event, navbarDao) {
        oNavbarDao = navbarDao;
        $scope.$emit('agentList.initialize', oNavbarDao);
    });
}]);
<commit_msg>[임대현] [NOBTS] spy 지연 시키기<commit_after>'use strict';

pinpointApp.controller('SpyCtrl', [ '$scope', '$timeout', '$routeParams', 'NavbarDao', function ($scope, $timeout, $routeParams, NavbarDao) {

    // define private variables
    var oNavbarDao;

    /**
     * initialize
     */
    $timeout(function () {
        oNavbarDao = new NavbarDao();
        if ($routeParams.application) {
            oNavbarDao.setApplication($routeParams.application);
        }
        if ($routeParams.period) {
            oNavbarDao.setPeriod(Number($routeParams.period, 10));
        }
        if ($routeParams.queryEndTime) {
            oNavbarDao.setQueryEndTime(Number($routeParams.queryEndTime, 10));
        }
        $scope.$emit('navbar.initialize', oNavbarDao);
    }, 100);

    /**
     * scope event on navbar.changed
     */
    $scope.$on('navbar.changed', function (event, navbarDao) {
        oNavbarDao = navbarDao;
        $scope.$emit('agentList.initialize', oNavbarDao);
    });
}]);
<|endoftext|>


<commit_before>const Color = "#470000";
class CorridorSprite extends Phaser.Sprite {

  constructor(game, x,y, width, height) {
    let bmd = game.add.bitmapData(width,height);
    // draw to the canvas context like normal
    bmd.ctx.beginPath();
    bmd.ctx.rect(0,0,width,height);
    bmd.ctx.fillStyle = Color;
    bmd.ctx.fill();

    super(game,x,y, bmd);
    this.center = { x: x + (width/2), y: y+ (height/2)};
    this.name = "corridorSprite";
  }

  overlapRoom(room) {
      if (this.x + this.width < room.x) return false; // a is left of b
      if (this.x > room.x + room.width) return false; // a is right of b
      if (this.y + this.height < room.y) return false; // a is above b
      if (this.y > room.y + room.height) return false; // a is below b
      return true; // boxes overlap
  }
}

export default CorridorSprite;<commit_msg>add borders<commit_after>const Color = "#470000";
class CorridorSprite extends Phaser.Sprite {

  constructor(game, x,y, width, height) {
    let bmd = game.add.bitmapData(width,height);
    // draw to the canvas context like normal
    bmd.ctx.beginPath();
    bmd.ctx.rect(0,0,width,height);
    bmd.ctx.fillStyle = Color;
    bmd.ctx.fill();

    super(game,x,y, bmd);
    this.center = { x: x + (width/2), y: y+ (height/2)};
    this.name = "corridorSprite";
    this.alpha = 0.2;
  }

  overlapRoom(room) {
      if (this.x + this.width < room.x) return false; // a is left of b
      if (this.x > room.x + room.width) return false; // a is right of b
      if (this.y + this.height < room.y) return false; // a is above b
      if (this.y > room.y + room.height) return false; // a is below b
      return true; // boxes overlap
  }
}

export default CorridorSprite;<|endoftext|>


<commit_before>var _SUPPORTS = require('../../../supports');

var proxy = {
    // DOC: Document these selectors
    ':child-even' : ':nth-child(even)',
    ':child-odd'  : ':nth-child(odd)',

    ':text'       : '[type="text"]',
    ':password'   : '[type="password"]',
    ':radio'      : '[type="radio"]',
    ':checkbox'   : '[type="checkbox"]',
    ':submit'     : '[type="submit"]',
    ':reset'      : '[type="reset"]',
    ':button'     : '[type="button"]',
    ':image'      : '[type="image"]',
    ':input'      : '[type="input"]',
    ':file'       : '[type="file"]',

    // See https://developer.mozilla.org/en-US/docs/Web/CSS/:checked
    ':selected'   : '[selected]'
};

// IE8
if (!_SUPPORTS.disabledSelector) {
    proxy[':disabled'] = '[disabled]';

    // DOC: No good way to polyfill this.
    // proxy[':enabled']  = ':not([disabled])';
}

// IE8
if (!_SUPPORTS.checkedSelector) {
    proxy[':checked']  = '[checked]';
}

module.exports = proxy;
<commit_msg>Fixed :selected proxy selector in IE8<commit_after>var _SUPPORTS = require('../../../supports');

var proxy = {
    // DOC: Document these selectors
    ':child-even' : ':nth-child(even)',
    ':child-odd'  : ':nth-child(odd)',

    ':text'       : '[type="text"]',
    ':password'   : '[type="password"]',
    ':radio'      : '[type="radio"]',
    ':checkbox'   : '[type="checkbox"]',
    ':submit'     : '[type="submit"]',
    ':reset'      : '[type="reset"]',
    ':button'     : '[type="button"]',
    ':image'      : '[type="image"]',
    ':input'      : '[type="input"]',
    ':file'       : '[type="file"]',

    // See https://developer.mozilla.org/en-US/docs/Web/CSS/:checked
    ':selected'   : '[selected="selected"]'
};

// IE8
if (!_SUPPORTS.disabledSelector) {
    proxy[':disabled'] = '[disabled]';

    // DOC: No good way to polyfill this.
    // proxy[':enabled']  = ':not([disabled])';
}

// IE8
if (!_SUPPORTS.checkedSelector) {
    proxy[':checked']  = '[checked]';
}

module.exports = proxy;
<|endoftext|>


<commit_before>// @ts-check
import { getPreloadPath } from './runtime-utils'

const noop = () => {}

const staticPreloadPaths = {}

export const loadPageData = async (to, next = noop) => {
  if (!to.matched || to.matched.length === 0) {
    return next()
  }

  // @ts-ignore
  const initialState = window._ream.initialState

  if (to.name === '404') {
    initialState.preload[to.path] = { notFound: true }
    return next()
  }

  const components = to.matched.map((m) => m.components.default)
  const hasPreload = components.some(
    (component) => component.$$preload || component.$$staticPreload
  )
  if (!hasPreload) {
    initialState.preload[to.path] = { hasPreload: false }
    return next()
  }

  const fetchPage = async (next) => {
    const result = {}

    for (const component of components) {
      if (component.$$preload || component.$$staticPreload) {
        const _result = await fetch(getPreloadPath(to.path)).then((res) => {
          if (res.status === 404) {
            return { notFound: true }
          }
          return res.json()
        })

        if (component.$$staticPreload) {
          staticPreloadPaths[to.path] = true
        }

        Object.assign(result, _result)
        // We only need to fetch server once
        break
      }
    }

    initialState.preload[to.path] = result

    next && next()
  }
  const prevResult = initialState.preload[to.path]
  if (staticPreloadPaths[to.path]) {
    // No need to fetch data for staticPreload pages when they have already fetched data once
    // Since the data doesn't change, hence "staticPreload"
    next()
  } else if (prevResult && prevResult.cacheFirst) {
    // Page props already exist, use cache and reinvalidate
    next()
    fetchPage()
  } else {
    await fetchPage(next)
  }
}

/**
 * Execute `preload` in router-level `beforeResolve`
 */
export const getBeforeResolve = () =>
  async function beforeResolve(to, from, next) {
    await loadPageData(to, next)
  }
<commit_msg>fix: handle redirect in browser<commit_after>// @ts-check
import { getPreloadPath } from './runtime-utils'

const noop = () => {}

export const loadPageData = async (to, next = noop) => {
  if (!to.matched || to.matched.length === 0) {
    return next()
  }

  // @ts-ignore
  const initialState = window._ream.initialState

  if (to.name === '404') {
    initialState.preload[to.path] = { notFound: true }
    return next()
  }

  const components = to.matched.map((m) => m.components.default)
  const hasPreload = components.some(
    (component) => component.$$preload || component.$$staticPreload
  )
  if (!hasPreload) {
    initialState.preload[to.path] = { hasPreload: false }
    return next()
  }

  const fetchPage = async (next) => {
    const result = {}

    for (const component of components) {
      if (component.$$preload || component.$$staticPreload) {
        const _result = await fetch(getPreloadPath(to.path)).then((res) => {
          if (res.status === 404) {
            return { notFound: true }
          }
          return res.json()
        })

        Object.assign(result, _result)
        // We only need to fetch server once
        break
      }
    }

    initialState.preload[to.path] = result

    next(result.redirect ? result.redirect.url : undefined)
  }

  await fetchPage(next)
}

/**
 * Execute `preload` in router-level `beforeResolve`
 */
export const getBeforeResolve = () =>
  async function beforeResolve(to, from, next) {
    await loadPageData(to, next)
  }
<|endoftext|>


<commit_before>import React from 'react'
import styled from 'styled-components'
import Text from './Text'

const H1 = Text.withComponent('h1').extend`
  font-size: 44px;
  font-weight: 900;
  line-height: 1.14;
`

const H2 = Text.withComponent('h2').extend`
  font-size: 32px;
  font-weight: 900;
  line-height: 1.12;
`

const H3 = Text.withComponent('h3').extend`
  font-size: 21px;
  font-weight: 800;
  line-height: 0.95;
}`

export default { H1, H2, H3 }
<commit_msg>chore(bonde-styleguide): mark important styles on title<commit_after>import React from 'react'
import styled from 'styled-components'
import Text from './Text'

const H1 = Text.withComponent('h1').extend`
  font-size: 44px !important;
  font-weight: 900 !important;
  line-height: 1.14 !important;
`

const H2 = Text.withComponent('h2').extend`
  font-size: 32px !important;
  font-weight: 900 !important;
  line-height: 1.12 !important;
`

const H3 = Text.withComponent('h3').extend`
  font-size: 21px !important;
  font-weight: 800 !important;
  line-height: 0.95 !important;
}`

export default { H1, H2, H3 }
<|endoftext|>


<commit_before>'use strict';

var querystring = require('querystring');
var _s = require('underscore.string');
var i18n = require('i18n');
var config = require('../config/environment');

const ytRegExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;

module.exports = {
  saveSession (res, token, remember) {
    var options = {httpOnly: true};
    if (remember) {
      options.maxAge = config.tokenMaxAge;
    }
    res.cookie(config.tokenCookieName, token, options);
  },
  clearSession (res) {
    res.clearCookie(config.tokenCookieName);
  },
  redirect (target, callbackUrl, res) {
    res.redirect(target + '?redir=' + querystring.escape(callbackUrl));
  },
  ogFromPost (post, limit) {
    let og = {
      author: post.writer.username,
      title: post.subject,
      link: config.origin + '/board/free/' + post.seq,
      description: _s(post.content).unescapeHTML().stripTags().truncate(limit).value() || post.subject,
      type: 'article'
    };

    let image = post.content.match(/<img.+?src=(['"])(.*?)\1/ig);
    let video = post.content.match(/<iframe.+?src=(['"])(.*?)\1/ig);

    if (image) {
      image = image[0].match(/src=(['"])(.*?)\1/)[2];
      if (image.startsWith('//')) {
        image = 'https:' + image;
      }
      og.image = image;
    }

    if (video) {
      video = video[0].match(/src=(['"])(.*?)\1/)[2];
      let ytMatch = (video.startsWith('//') ? 'https:' + video : video).match(ytRegExp);
      if (ytMatch && ytMatch[1].length === 11) {
        let youtubeId = ytMatch[1];
        video = 'https://www.youtube.com/watch?v=' + youtubeId;
        og.video = video;
        og.videoProvider = 'Youtube';
      }
    }

    return og;
  },
  makeError (response) {
    let err = new Error(JSON.stringify({
      type: 'api error',
      api: response.req.agent.protocol + '//' + response.req._headers.host + response.req.path,
      data: response.data
    }, null, 2));
    err.status = response.statusCode;
    err.statusMessage = response.statusMessage;
    return err;
  },
  makeForbidden() {
    let err = new Error(i18n.__('common.msg.error.401'));
    err.status = 401;
    err.statusMessage = 'Unauthorized';
    return err;
  }
};<commit_msg>refactor - 서버연결 오류 에러메세지 추가<commit_after>'use strict';

var querystring = require('querystring');
var _s = require('underscore.string');
var i18n = require('i18n');
var config = require('../config/environment');

const ytRegExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;

module.exports = {
  saveSession (res, token, remember) {
    var options = {httpOnly: true};
    if (remember) {
      options.maxAge = config.tokenMaxAge;
    }
    res.cookie(config.tokenCookieName, token, options);
  },
  clearSession (res) {
    res.clearCookie(config.tokenCookieName);
  },
  redirect (target, callbackUrl, res) {
    res.redirect(target + '?redir=' + querystring.escape(callbackUrl));
  },
  ogFromPost (post, limit) {
    let og = {
      author: post.writer.username,
      title: post.subject,
      link: config.origin + '/board/free/' + post.seq,
      description: _s(post.content).unescapeHTML().stripTags().truncate(limit).value() || post.subject,
      type: 'article'
    };

    let image = post.content.match(/<img.+?src=(['"])(.*?)\1/ig);
    let video = post.content.match(/<iframe.+?src=(['"])(.*?)\1/ig);

    if (image) {
      image = image[0].match(/src=(['"])(.*?)\1/)[2];
      if (image.startsWith('//')) {
        image = 'https:' + image;
      }
      og.image = image;
    }

    if (video) {
      video = video[0].match(/src=(['"])(.*?)\1/)[2];
      let ytMatch = (video.startsWith('//') ? 'https:' + video : video).match(ytRegExp);
      if (ytMatch && ytMatch[1].length === 11) {
        let youtubeId = ytMatch[1];
        video = 'https://www.youtube.com/watch?v=' + youtubeId;
        og.video = video;
        og.videoProvider = 'Youtube';
      }
    }

    return og;
  },
  makeError (response) {
    let err = new Error(JSON.stringify({
      type: response.req ? 'api error' : 'server unavailable',
      api: response.req ? `${response.req.agent.protocol}${response.req._headers.host}${response.req.path}` : '',
      data: response.data
    }, null, 2));
    err.status = response.statusCode;
    err.statusMessage = response.statusMessage;
    return err;
  },
  makeForbidden() {
    let err = new Error(i18n.__('common.msg.error.401'));
    err.status = 401;
    err.statusMessage = 'Unauthorized';
    return err;
  }
};<|endoftext|>