<commit_before>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/4/12
 * Time: 11:06 PM
 * To change this template use File | Settings | File Templates.
 */
define([
    'config/anthill',
    'modules/Model'
], function defineGalleryModel(AntHill, BaseModel) {

    /**
     * Define Gallery model
     * @extends AntHill
     * @extends BaseModel
     * @class GalleryModel
     * @constructor
     */
    var GalleryModel = function GalleryModel() {

        /**
         * Define provider types
         * @type {{regular: string, text: string, video: string, map: string, files: string, image: string, social: string}}
         */
        this.dataTypes = {
            regular: 'Regular widgets',
            text: 'Text editor',
            video: 'Video player',
            map: 'Map widgets',
            files: 'Show file',
            image: 'Image gallery',
            social: 'Social data'
        };

        /**
         * Define static data
         * @member GalleryModel
         * @type {*[]}
         */
        this.staticData = [
            {
                name: 'Page Tabs',
                description: 'Show page tabs',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 5
                },
                type: 'regular',
                resource: 'page.tabs'
            },
            {
                name: 'Empty',
                description: 'Empty widget',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'regular',
                resource: 'empty'
            },
            {
                name: 'Text Editor',
                description: 'Text Editor',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 7
                },
                type: 'text',
                resource: 'text.editor'
            },
            {
                name: 'Dropbox',
                description: 'Dropbox is a free service that lets you bring your photos, docs, and videos anywhere and share them easily.',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'files',
                resource: 'dropbox'
            },
            {
                name: 'Map Locator',
                description: 'Map locator',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'map.locator'
            },
            {
                name: 'Avatar',
                description: 'Pick a photo and put it as your Avatar',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'avatar'
            },
            {
                name: 'JW Player',
                description: 'JW Player powers online publishing, with clients ranging in size from Fortune 500 companies to individual bloggers',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'jwplayer'
            },
            {
                name: 'Youtube',
                description: 'YouTube provides a forum for people to connect, inform, and inspire others across the globe and acts as a distribution platform for original content creators and advertisers large and small',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'youtube'
            },
            {
                name: 'Quicktime',
                description: 'A powerful multimedia technology with a built-in media player, QuickTime lets you view internet video, HD movie trailers, and personal media in a wide range of file formats',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'quicktime'
            },
            {
                name: 'Vimeo',
                description: 'Vimeo is video + you. We put your videos first and give you the best ways to share, discover, and be inspired',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'vimeo'
            },
            {
                name: 'Image',
                description: 'A simple image widget that uses the native media manager to add image widgets to your site',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'image'
            },
            {
                name: 'Image Gallery',
                description: 'Image gallery provides an image viewer',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'image.gallery'
            },
            {
                name: 'RSS',
                description: 'Subscribing to a website RSS removes the need for the user to manually check the web site for new content',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 5
                },
                type: 'social',
                resource: 'rss'
            },
            {
                name: 'Twits',
                description: 'Show unique twitter thread',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 5
                },
                type: 'social',
                resource: 'twits'
            },
            {
                name: 'Pdf',
                description: 'Portable Document Format (PDF) is a file format used to present documents in a manner independent of application software, hardware, and operating systems',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'files',
                resource: 'pdf'
            },
            {
                name: 'Geolocation',
                description: 'Geolocation is the identification of the real-world geographic location of an object, such as a radar, mobile phone or an Internet-connected computer terminal',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'geolocation'
            },
            {
                name: 'Open Weather Map',
                description: 'The OpenWeatherMap service provides free weather data and forecast API suitable for any cartographic services like web and smartphones applications',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'open.weather.map'
            },
            {
                name: 'Login',
                description: 'Login to your page',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'social',
                resource: 'login'
            },
            {
                name: 'Share',
                description: 'Share your page with your friends',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 10
                },
                type: 'social',
                resource: 'share'
            },
            {
                name: 'Adobe Flash player',
                description: 'Adobe Flash Player is the standard for delivering high-impact, rich Web content. Designs, animation, and application user interfaces are deployed immediately across all browsers and platforms, attracting and engaging users with a rich Web experience.',
                thumbnail: '',
                dimensions: {
                    width: 15,
                    height: 15
                },
                type: 'video',
                resource: 'swf'
            },
            {
                name: 'Rutube',
                description: 'Rutube is a web video streaming service targeted at Russian speakers',
                thumbnail: '',
                dimensions: {
                    width: 15,
                    height: 15
                },
                type: 'video',
                resource: 'rutube'
            }

        ];

        /**
         * Define providers
         * @member GalleryModel
         * @type {{indoor: {name: string, data: *[]}}}
         */
        this.providers = {
            all: {
                name: 'All widgets',
                key: 'all',
                data: this.staticData
            }
        };

        /**
         * Define default provider
         * @member GalleryModel
         * @type {{name: string, data: *[]}[]}
         */
        this.defaultProvider = this.getProvidersList().all;

        /**
         * Define current provider
         * @member GalleryModel
         */
        this.currentProvider = this.defaultProvider;
    };

    return GalleryModel.extend('GalleryModel', {

        /**
         * Get data provider
         * @member GalleryModel
         * @param provider
         * @returns {*}
         */
        getDataProvider: function getDataProvider(provider) {
            return provider.data;
        },

        /**
         * Get providers list
         * @member GalleryModel
         * @returns {*}
         */
        getProvidersList: function getProvidersList() {
            return this.providers;
        },

        /**
         * Set provider as current
         * @member GalleryModel
         * @param {string} key
         */
        setProviderAsCurrent: function setProviderAsCurrent(key) {

            /**
             * Define provider
             * @type {*}
             */
            var provider = this.providers[key];

            if (!provider) {
                provider = this.defaultProvider;
                this.scope.logger.warn('Undefined provider, set default', provider);
            }

            this.currentProvider = provider;
            this.scope.logger.debug('Current provider', provider);
        },

        /**
         * Set widget to provider
         * @member GalleryModel
         * @param {{}} meta
         */
        setProvider: function setProvider(meta) {

            /**
             * Get providers list
             * @type {*}
             */
            var providers = this.getProvidersList();

            /**
             * Get data types
             * @type {{regular: string, text: string, video: string, map: string, files: string, image: string, social: string}}
             */
            var dataTypes = this.dataTypes;

            if (meta.type) {

                providers[meta.type] = this.base.define(
                    providers[meta.type], {
                        name: dataTypes[meta.type] || meta.type,
                        key: meta.type,
                        data: []
                    },
                    true
                );

                providers[meta.type].data.push(meta);

            } else {

                providers.all.data.push(meta);
            }
        }

    }, AntHill.prototype, BaseModel.prototype);
});<commit_msg>enlarge page tabs<commit_after>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/4/12
 * Time: 11:06 PM
 * To change this template use File | Settings | File Templates.
 */
define([
    'config/anthill',
    'modules/Model'
], function defineGalleryModel(AntHill, BaseModel) {

    /**
     * Define Gallery model
     * @extends AntHill
     * @extends BaseModel
     * @class GalleryModel
     * @constructor
     */
    var GalleryModel = function GalleryModel() {

        /**
         * Define provider types
         * @type {{regular: string, text: string, video: string, map: string, files: string, image: string, social: string}}
         */
        this.dataTypes = {
            regular: 'Regular widgets',
            text: 'Text editor',
            video: 'Video player',
            map: 'Map widgets',
            files: 'Show file',
            image: 'Image gallery',
            social: 'Social data'
        };

        /**
         * Define static data
         * @member GalleryModel
         * @type {*[]}
         */
        this.staticData = [
            {
                name: 'Page Tabs',
                description: 'Show page tabs',
                thumbnail: '',
                dimensions: {
                    width: 30,
                    height: 5
                },
                type: 'regular',
                resource: 'page.tabs'
            },
            {
                name: 'Empty',
                description: 'Empty widget',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'regular',
                resource: 'empty'
            },
            {
                name: 'Text Editor',
                description: 'Text Editor',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 7
                },
                type: 'text',
                resource: 'text.editor'
            },
            {
                name: 'Dropbox',
                description: 'Dropbox is a free service that lets you bring your photos, docs, and videos anywhere and share them easily.',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'files',
                resource: 'dropbox'
            },
            {
                name: 'Map Locator',
                description: 'Map locator',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'map.locator'
            },
            {
                name: 'Avatar',
                description: 'Pick a photo and put it as your Avatar',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'avatar'
            },
            {
                name: 'JW Player',
                description: 'JW Player powers online publishing, with clients ranging in size from Fortune 500 companies to individual bloggers',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'jwplayer'
            },
            {
                name: 'Youtube',
                description: 'YouTube provides a forum for people to connect, inform, and inspire others across the globe and acts as a distribution platform for original content creators and advertisers large and small',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'youtube'
            },
            {
                name: 'Quicktime',
                description: 'A powerful multimedia technology with a built-in media player, QuickTime lets you view internet video, HD movie trailers, and personal media in a wide range of file formats',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'quicktime'
            },
            {
                name: 'Vimeo',
                description: 'Vimeo is video + you. We put your videos first and give you the best ways to share, discover, and be inspired',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'video',
                resource: 'vimeo'
            },
            {
                name: 'Image',
                description: 'A simple image widget that uses the native media manager to add image widgets to your site',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'image'
            },
            {
                name: 'Image Gallery',
                description: 'Image gallery provides an image viewer',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'image',
                resource: 'image.gallery'
            },
            {
                name: 'RSS',
                description: 'Subscribing to a website RSS removes the need for the user to manually check the web site for new content',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 5
                },
                type: 'social',
                resource: 'rss'
            },
            {
                name: 'Twits',
                description: 'Show unique twitter thread',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 5
                },
                type: 'social',
                resource: 'twits'
            },
            {
                name: 'Pdf',
                description: 'Portable Document Format (PDF) is a file format used to present documents in a manner independent of application software, hardware, and operating systems',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'files',
                resource: 'pdf'
            },
            {
                name: 'Geolocation',
                description: 'Geolocation is the identification of the real-world geographic location of an object, such as a radar, mobile phone or an Internet-connected computer terminal',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'geolocation'
            },
            {
                name: 'Open Weather Map',
                description: 'The OpenWeatherMap service provides free weather data and forecast API suitable for any cartographic services like web and smartphones applications',
                thumbnail: '',
                dimensions: {
                    width: 10,
                    height: 10
                },
                type: 'map',
                resource: 'open.weather.map'
            },
            {
                name: 'Login',
                description: 'Login to your page',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 5
                },
                type: 'social',
                resource: 'login'
            },
            {
                name: 'Share',
                description: 'Share your page with your friends',
                thumbnail: '',
                dimensions: {
                    width: 5,
                    height: 10
                },
                type: 'social',
                resource: 'share'
            },
            {
                name: 'Adobe Flash player',
                description: 'Adobe Flash Player is the standard for delivering high-impact, rich Web content. Designs, animation, and application user interfaces are deployed immediately across all browsers and platforms, attracting and engaging users with a rich Web experience.',
                thumbnail: '',
                dimensions: {
                    width: 15,
                    height: 15
                },
                type: 'video',
                resource: 'swf'
            },
            {
                name: 'Rutube',
                description: 'Rutube is a web video streaming service targeted at Russian speakers',
                thumbnail: '',
                dimensions: {
                    width: 15,
                    height: 15
                },
                type: 'video',
                resource: 'rutube'
            }

        ];

        /**
         * Define providers
         * @member GalleryModel
         * @type {{indoor: {name: string, data: *[]}}}
         */
        this.providers = {
            all: {
                name: 'All widgets',
                key: 'all',
                data: this.staticData
            }
        };

        /**
         * Define default provider
         * @member GalleryModel
         * @type {{name: string, data: *[]}[]}
         */
        this.defaultProvider = this.getProvidersList().all;

        /**
         * Define current provider
         * @member GalleryModel
         */
        this.currentProvider = this.defaultProvider;
    };

    return GalleryModel.extend('GalleryModel', {

        /**
         * Get data provider
         * @member GalleryModel
         * @param provider
         * @returns {*}
         */
        getDataProvider: function getDataProvider(provider) {
            return provider.data;
        },

        /**
         * Get providers list
         * @member GalleryModel
         * @returns {*}
         */
        getProvidersList: function getProvidersList() {
            return this.providers;
        },

        /**
         * Set provider as current
         * @member GalleryModel
         * @param {string} key
         */
        setProviderAsCurrent: function setProviderAsCurrent(key) {

            /**
             * Define provider
             * @type {*}
             */
            var provider = this.providers[key];

            if (!provider) {
                provider = this.defaultProvider;
                this.scope.logger.warn('Undefined provider, set default', provider);
            }

            this.currentProvider = provider;
            this.scope.logger.debug('Current provider', provider);
        },

        /**
         * Set widget to provider
         * @member GalleryModel
         * @param {{}} meta
         */
        setProvider: function setProvider(meta) {

            /**
             * Get providers list
             * @type {*}
             */
            var providers = this.getProvidersList();

            /**
             * Get data types
             * @type {{regular: string, text: string, video: string, map: string, files: string, image: string, social: string}}
             */
            var dataTypes = this.dataTypes;

            if (meta.type) {

                providers[meta.type] = this.base.define(
                    providers[meta.type], {
                        name: dataTypes[meta.type] || meta.type,
                        key: meta.type,
                        data: []
                    },
                    true
                );

                providers[meta.type].data.push(meta);

            } else {

                providers.all.data.push(meta);
            }
        }

    }, AntHill.prototype, BaseModel.prototype);
});<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import qs from 'query-string';

const INDC = ['INDC Submitted', 'First NDC Submitted', 'Second NDC Submitted'];
const NDC = ['First NDC Submitted', 'Second NDC Submitted'];

const getCountries = state => (state.countries && state.countries.data) || null;
const getIndicatorsData = state =>
  (state.compareAll.data && state.compareAll.data.indicators) || null;
// export const getLoading = state => state.compareAll.loading || null;
const getQuery = (state, { search }) => search || '';

const getCountryOptions = createSelector([getCountries], countries => {
  if (!countries) return [];
  return countries.map(({ wri_standard_name, iso_code3 }) => ({
    label: wri_standard_name,
    value: iso_code3
  }));
});

const getSelectedCountries = createSelector(
  [getCountryOptions, getQuery],
  (countriesData, query) => {
    if (!countriesData && !countriesData.length && !query) return null;
    const { country0, country1, country2 } = query;
    return {
      country0,
      country1,
      country2
    };
  }
);

const getSelectedDocuments = createSelector([getQuery], query => {
  if (!query) return null;
  const { document0, document1, document2 } = query;
  return {
    document0,
    document1,
    document2
  };
});

const getDocumentsOptionsByCountry = createSelector(
  [getSelectedCountries, getIndicatorsData],
  (selectedCountries, indicators) => {
    if (!selectedCountries || !indicators || !indicators.length) return null;

    const ndcIndicator = indicators.find(i => i.slug === 'submission');
    const ltsIndicator = indicators.find(i => i.slug === 'lts_submission');

    const rows = Object.values(selectedCountries).reduce((acc, country) => {
      if (!country) return acc;

      const countryNDC = ndcIndicator.locations[country];
      const countryLTS = ltsIndicator.locations[country];

      let documents = [];

      if (INDC.includes(countryNDC.value)) {
        documents = [...documents, { label: 'INDC', value: 'INDC' }];
      }
      if (NDC.includes(countryNDC.value)) {
        documents = [...documents, { label: 'NDC', value: 'NDC' }];
      }
      if (countryNDC.value === 'Second NDC Submitted') {
        documents = [...documents, { label: '2nd NDC', value: '2nd NDC' }];
      }
      if (countryLTS && countryLTS.value === 'Long-term Strategy Submitted') {
        documents = [...documents, { label: 'LTS', value: 'LTS' }];
      }

      return {
        ...acc,
        [country]: documents
      };
    }, {});
    return rows;
  }
);

export const getFiltersData = createSelector(
  [
    getSelectedCountries,
    getCountryOptions,
    getSelectedDocuments,
    getDocumentsOptionsByCountry
  ],
  (selectedCountries, countryOptions, selectedDocuments, documentOptions) => {
    if (!countryOptions || !countryOptions.length || !selectedCountries) {
      return null;
    }

    const filtersData = Object.values(selectedCountries).map((country, i) => ({
      key: `filters-group-${i}`,
      countryParam: `country${i}`,
      countryValue: countryOptions.find(({ value }) => country === value),
      contriesOptions: countryOptions,
      documentParam: `document${i}`,
      documentValue:
        documentOptions &&
        documentOptions[country] &&
        documentOptions[country].find(
          ({ value }) => value === selectedDocuments[`document${i}`]
        ),
      documentOptions: documentOptions ? documentOptions[country] : []
    }));

    return filtersData;
  }
);

export const getAnchorLinks = createSelector(
  [state => state.route.routes || [], state => state.location.search],
  (routes, search) => {
    const searchQuery = qs.parse(search);
    const searchParams = { locations: searchQuery.locations };
    return routes
      .filter(route => route.anchor)
      .map(route => ({
        label: route.label,
        path: `/custom-compare/${route.param ? route.param : ''}`,
        search: `?${qs.stringify(searchParams)}`
      }));
  }
);

export default {
  getAnchorLinks,
  getFiltersData,
  getCountryOptions
};
<commit_msg>Remove commented code<commit_after>import { createSelector } from 'reselect';
import qs from 'query-string';

const INDC = ['INDC Submitted', 'First NDC Submitted', 'Second NDC Submitted'];
const NDC = ['First NDC Submitted', 'Second NDC Submitted'];

const getCountries = state => (state.countries && state.countries.data) || null;
const getIndicatorsData = state =>
  (state.compareAll.data && state.compareAll.data.indicators) || null;
const getQuery = (state, { search }) => search || '';

const getCountryOptions = createSelector([getCountries], countries => {
  if (!countries) return [];
  return countries.map(({ wri_standard_name, iso_code3 }) => ({
    label: wri_standard_name,
    value: iso_code3
  }));
});

const getSelectedCountries = createSelector(
  [getCountryOptions, getQuery],
  (countriesData, query) => {
    if (!countriesData && !countriesData.length && !query) return null;
    const { country0, country1, country2 } = query;
    return {
      country0,
      country1,
      country2
    };
  }
);

const getSelectedDocuments = createSelector([getQuery], query => {
  if (!query) return null;
  const { document0, document1, document2 } = query;
  return {
    document0,
    document1,
    document2
  };
});

const getDocumentsOptionsByCountry = createSelector(
  [getSelectedCountries, getIndicatorsData],
  (selectedCountries, indicators) => {
    if (!selectedCountries || !indicators || !indicators.length) return null;

    const ndcIndicator = indicators.find(i => i.slug === 'submission');
    const ltsIndicator = indicators.find(i => i.slug === 'lts_submission');

    const rows = Object.values(selectedCountries).reduce((acc, country) => {
      if (!country) return acc;

      const countryNDC = ndcIndicator.locations[country];
      const countryLTS = ltsIndicator.locations[country];

      let documents = [];

      if (INDC.includes(countryNDC.value)) {
        documents = [...documents, { label: 'INDC', value: 'INDC' }];
      }
      if (NDC.includes(countryNDC.value)) {
        documents = [...documents, { label: 'NDC', value: 'NDC' }];
      }
      if (countryNDC.value === 'Second NDC Submitted') {
        documents = [...documents, { label: '2nd NDC', value: '2nd NDC' }];
      }
      if (countryLTS && countryLTS.value === 'Long-term Strategy Submitted') {
        documents = [...documents, { label: 'LTS', value: 'LTS' }];
      }

      return {
        ...acc,
        [country]: documents
      };
    }, {});
    return rows;
  }
);

export const getFiltersData = createSelector(
  [
    getSelectedCountries,
    getCountryOptions,
    getSelectedDocuments,
    getDocumentsOptionsByCountry
  ],
  (selectedCountries, countryOptions, selectedDocuments, documentOptions) => {
    if (!countryOptions || !countryOptions.length || !selectedCountries) {
      return null;
    }

    const filtersData = Object.values(selectedCountries).map((country, i) => ({
      key: `filters-group-${i}`,
      countryParam: `country${i}`,
      countryValue: countryOptions.find(({ value }) => country === value),
      contriesOptions: countryOptions,
      documentParam: `document${i}`,
      documentValue:
        documentOptions &&
        documentOptions[country] &&
        documentOptions[country].find(
          ({ value }) => value === selectedDocuments[`document${i}`]
        ),
      documentOptions: documentOptions ? documentOptions[country] : []
    }));

    return filtersData;
  }
);

export const getAnchorLinks = createSelector(
  [state => state.route.routes || [], state => state.location.search],
  (routes, search) => {
    const searchQuery = qs.parse(search);
    const searchParams = { locations: searchQuery.locations };
    return routes
      .filter(route => route.anchor)
      .map(route => ({
        label: route.label,
        path: `/custom-compare/${route.param ? route.param : ''}`,
        search: `?${qs.stringify(searchParams)}`
      }));
  }
);

export default {
  getAnchorLinks,
  getFiltersData,
  getCountryOptions
};
<|endoftext|>


<commit_before>import { injectGlobalStyles, ThemeProviderV3 } from "@artsy/palette"
import { MediaContextProvider } from "Utils/Responsive"
import { createRelaySSREnvironment } from "System/Relay/createRelaySSREnvironment"
import { SystemContextProvider } from "System"

const { GlobalStyles } = injectGlobalStyles()

const relayEnvironment = createRelaySSREnvironment({
  metaphysicsEndpoint: "https://metaphysics-staging.artsy.net/v2",
  cache: JSON.parse(window.__RELAY_BOOTSTRAP__ || "{}"),
})

export const decorators = [
  Story => {
    return (
      <SystemContextProvider relayEnvironment={relayEnvironment}>
        <MediaContextProvider>
          <ThemeProviderV3>
            <GlobalStyles />
            <Story />
          </ThemeProviderV3>
        </MediaContextProvider>
      </SystemContextProvider>
    )
  },
]

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
}
<commit_msg>fix(storybook): provide tracking context to all stories<commit_after>import { injectGlobalStyles, ThemeProviderV3 } from "@artsy/palette"
import { MediaContextProvider } from "Utils/Responsive"
import { createRelaySSREnvironment } from "System/Relay/createRelaySSREnvironment"
import { SystemContextProvider } from "System"
import { track } from "react-tracking"

const { GlobalStyles } = injectGlobalStyles()

const relayEnvironment = createRelaySSREnvironment({
  metaphysicsEndpoint: "https://metaphysics-staging.artsy.net/v2",
  cache: JSON.parse(window.__RELAY_BOOTSTRAP__ || "{}"),
})

export const decorators = [
  Story => {
    const Tracked = track()(Story)

    return (
      <SystemContextProvider relayEnvironment={relayEnvironment}>
        <MediaContextProvider>
          <ThemeProviderV3>
            <GlobalStyles />
            <Tracked />
          </ThemeProviderV3>
        </MediaContextProvider>
      </SystemContextProvider>
    )
  },
]

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
}
<|endoftext|>


<commit_before>import 'bulma/css/bulma.css';

export const parameters = {
    actions: { argTypesRegex: "^on[A-Z].*" },
}<commit_msg>fix bulma default color for links changed<commit_after>import 'bulma/css/bulma.css';
import '../pages/main.css'

export const parameters = {
    actions: { argTypesRegex: "^on[A-Z].*" },
}<|endoftext|>


<commit_before>var Utils = require("./util"),
    Headers = require("./headers"),
    Constants = Utils.Constants,
    Methods = require("./methods");

module.exports = function (/*Buffer*/input) {

    var _entryHeader = new Headers.EntryHeader(),
        _entryName = Buffer.alloc(0),
        _comment = Buffer.alloc(0),
        _isDirectory = false,
        uncompressedData = null,
        _extra = Buffer.alloc(0);

    function getCompressedDataFromZip() {
        if (!input || !Buffer.isBuffer(input)) {
            return Buffer.alloc(0);
        }
        _entryHeader.loadDataHeaderFromBinary(input);
        return input.slice(_entryHeader.realDataOffset, _entryHeader.realDataOffset + _entryHeader.compressedSize)
    }

    function crc32OK(data) {
        // if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written
        if ((_entryHeader.flags & 0x8) !== 0x8) {
           if (Utils.crc32(data) !== _entryHeader.crc) {
               return false;
           }
        } else {
            // @TODO: load and check data descriptor header
            // The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure
            // (optionally preceded by a 4-byte signature) immediately after the compressed data:
        }
        return true;
    }

    function decompress(/*Boolean*/async, /*Function*/callback, /*String*/pass) {
        if(typeof callback === 'undefined' && typeof async === 'string') {
            pass=async;
            async=void 0;
        }
        if (_isDirectory) {
            if (async && callback) {
                callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR); //si added error.
            }
            return Buffer.alloc(0);
        }

        var compressedData = getCompressedDataFromZip();

        if (compressedData.length === 0) {
            if (async && callback) callback(compressedData, Utils.Errors.NO_DATA);//si added error.
            return compressedData;
        }

        var data = Buffer.alloc(_entryHeader.size);

        switch (_entryHeader.method) {
            case Utils.Constants.STORED:
                compressedData.copy(data);
                if (!crc32OK(data)) {
                    if (async && callback) callback(data, Utils.Errors.BAD_CRC);//si added error
                    return Utils.Errors.BAD_CRC;
                } else {//si added otherwise did not seem to return data.
                    if (async && callback) callback(data);
                    return data;
                }
            case Utils.Constants.DEFLATED:
                var inflater = new Methods.Inflater(compressedData);
                if (!async) {
                    var result = inflater.inflate(data);
                    result.copy(data, 0);
                    if (!crc32OK(data)) {
                        console.warn(Utils.Errors.BAD_CRC + " " + _entryName.toString())
                    }
                    return data;
                } else {
                    inflater.inflateAsync(function(result) {
                        result.copy(data, 0);
                        if (!crc32OK(data)) {
                            if (callback) callback(data, Utils.Errors.BAD_CRC); //si added error
                        } else { //si added otherwise did not seem to return data.
                            if (callback) callback(data);
                        }
                    })
                }
                break;
            default:
                if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD);
                return Utils.Errors.UNKNOWN_METHOD;
        }
    }

    function compress(/*Boolean*/async, /*Function*/callback) {
        if ((!uncompressedData || !uncompressedData.length) && Buffer.isBuffer(input)) {
            // no data set or the data wasn't changed to require recompression
            if (async && callback) callback(getCompressedDataFromZip());
            return getCompressedDataFromZip();
        }

        if (uncompressedData.length && !_isDirectory) {
            var compressedData;
            // Local file header
            switch (_entryHeader.method) {
                case Utils.Constants.STORED:
                    _entryHeader.compressedSize = _entryHeader.size;

                    compressedData = Buffer.alloc(uncompressedData.length);
                    uncompressedData.copy(compressedData);

                    if (async && callback) callback(compressedData);
                    return compressedData;
                default:
                case Utils.Constants.DEFLATED:

                    var deflater = new Methods.Deflater(uncompressedData);
                    if (!async) {
                        var deflated = deflater.deflate();
                        _entryHeader.compressedSize = deflated.length;
                        return deflated;
                    } else {
                        deflater.deflateAsync(function(data) {
                            compressedData = Buffer.alloc(data.length);
                            _entryHeader.compressedSize = data.length;
                            data.copy(compressedData);
                            callback && callback(compressedData);
                        })
                    }
                    deflater = null;
                    break;
            }
        } else {
            if (async && callback) {
                callback(Buffer.alloc(0));
            } else {
                return Buffer.alloc(0);
            }
        }
    }

    function readUInt64LE(buffer, offset) {
        return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
    }

    function parseExtra(data) {
        var offset = 0;
        var signature, size, part;
        while(offset<data.length) {
            signature = data.readUInt16LE(offset);
            offset += 2;
            size = data.readUInt16LE(offset);
            offset += 2;
            part = data.slice(offset, offset+size);
            offset += size;
            if(Constants.ID_ZIP64 === signature) {
                parseZip64ExtendedInformation(part);
            }
        }
    }

    //Override header field values with values from the ZIP64 extra field
    function parseZip64ExtendedInformation(data) {
        var size, compressedSize, offset, diskNumStart;

        if(data.length >= Constants.EF_ZIP64_SCOMP) {
            size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
            if(_entryHeader.size === Constants.EF_ZIP64_OR_32) {
                _entryHeader.size = size;
            }
        }
        if(data.length >= Constants.EF_ZIP64_RHO) {
            compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
            if(_entryHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
                _entryHeader.compressedSize = compressedSize;
            }
        }
        if(data.length >= Constants.EF_ZIP64_DSN) {
            offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
            if(_entryHeader.offset === Constants.EF_ZIP64_OR_32) {
                _entryHeader.offset = offset;
            }
        }
        if(data.length >= Constants.EF_ZIP64_DSN+4) {
            diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
            if(_entryHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
                _entryHeader.diskNumStart = diskNumStart;
            }
        }
    }

    return {
        get entryName () { return _entryName.toString(); },
        get rawEntryName() { return _entryName; },
        set entryName (val) {
            _entryName = Utils.toBuffer(val);
            var lastChar = _entryName[_entryName.length - 1];
            _isDirectory = (lastChar === 47) || (lastChar === 92);
            _entryHeader.fileNameLength = _entryName.length;
        },

        get extra () { return _extra; },
        set extra (val) {
            _extra = val;
            _entryHeader.extraLength = val.length;
            parseExtra(val);
        },

        get comment () { return _comment.toString(); },
        set comment (val) {
            _comment = Utils.toBuffer(val);
            _entryHeader.commentLength = _comment.length;
        },

        get name () { var n = _entryName.toString(); return _isDirectory ? n.substr(n.length - 1).split("/").pop() : n.split("/").pop(); },
        get isDirectory () { return _isDirectory },

        getCompressedData : function() {
            return compress(false, null)
        },

        getCompressedDataAsync : function(/*Function*/callback) {
            compress(true, callback)
        },

        setData : function(value) {
            uncompressedData = Utils.toBuffer(value);
            if (!_isDirectory && uncompressedData.length) {
                _entryHeader.size = uncompressedData.length;
                _entryHeader.method = Utils.Constants.STORED;
                _entryHeader.crc = Utils.crc32(value);
                _entryHeader.changed = true;
            } else { // folders and blank files should be stored
                _entryHeader.method = Utils.Constants.STORED;
            }
        },

        getData : function(pass) {
            if (_entryHeader.changed) {
				return uncompressedData;
			} else {
				return decompress(false, null, pass);
            }
        },

        getDataAsync : function(/*Function*/callback, pass) {
			if (_entryHeader.changed) {
				callback(uncompressedData)
			} else {
				decompress(true, callback, pass)
            }
        },

        set attr(attr) { _entryHeader.attr = attr; },
        get attr() { return _entryHeader.attr; },

        set header(/*Buffer*/data) {
            _entryHeader.loadFromBinary(data);
        },

        get header() {
            return _entryHeader;
        },

        packHeader : function() {
            var header = _entryHeader.entryHeaderToBinary();
            // add
            _entryName.copy(header, Utils.Constants.CENHDR);
            if (_entryHeader.extraLength) {
                _extra.copy(header, Utils.Constants.CENHDR + _entryName.length)
            }
            if (_entryHeader.commentLength) {
                _comment.copy(header, Utils.Constants.CENHDR + _entryName.length + _entryHeader.extraLength, _comment.length);
            }
            return header;
        },

        toString : function() {
            return '{\n' +
                '\t"entryName" : "' + _entryName.toString() + "\",\n" +
                '\t"name" : "' + (_isDirectory ? _entryName.toString().replace(/\/$/, '').split("/").pop() : _entryName.toString().split("/").pop()) + "\",\n" +
                '\t"comment" : "' + _comment.toString() + "\",\n" +
                '\t"isDirectory" : ' + _isDirectory + ",\n" +
                '\t"header" : ' + _entryHeader.toString().replace(/\t/mg, "\t\t").replace(/}/mg, "\t}")  + ",\n" +
                '\t"compressedData" : <' + (input && input.length  + " bytes buffer" || "null") + ">\n" +
                '\t"data" : <' + (uncompressedData && uncompressedData.length  + " bytes buffer" || "null") + ">\n" +
                '}';
        }
    }
};
<commit_msg>change default compression method for added files back to DEFLATED from STORED (revert #139)<commit_after>var Utils = require("./util"),
    Headers = require("./headers"),
    Constants = Utils.Constants,
    Methods = require("./methods");

module.exports = function (/*Buffer*/input) {

    var _entryHeader = new Headers.EntryHeader(),
        _entryName = Buffer.alloc(0),
        _comment = Buffer.alloc(0),
        _isDirectory = false,
        uncompressedData = null,
        _extra = Buffer.alloc(0);

    function getCompressedDataFromZip() {
        if (!input || !Buffer.isBuffer(input)) {
            return Buffer.alloc(0);
        }
        _entryHeader.loadDataHeaderFromBinary(input);
        return input.slice(_entryHeader.realDataOffset, _entryHeader.realDataOffset + _entryHeader.compressedSize)
    }

    function crc32OK(data) {
        // if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written
        if ((_entryHeader.flags & 0x8) !== 0x8) {
           if (Utils.crc32(data) !== _entryHeader.crc) {
               return false;
           }
        } else {
            // @TODO: load and check data descriptor header
            // The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure
            // (optionally preceded by a 4-byte signature) immediately after the compressed data:
        }
        return true;
    }

    function decompress(/*Boolean*/async, /*Function*/callback, /*String*/pass) {
        if(typeof callback === 'undefined' && typeof async === 'string') {
            pass=async;
            async=void 0;
        }
        if (_isDirectory) {
            if (async && callback) {
                callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR); //si added error.
            }
            return Buffer.alloc(0);
        }

        var compressedData = getCompressedDataFromZip();

        if (compressedData.length === 0) {
            if (async && callback) callback(compressedData, Utils.Errors.NO_DATA);//si added error.
            return compressedData;
        }

        var data = Buffer.alloc(_entryHeader.size);

        switch (_entryHeader.method) {
            case Utils.Constants.STORED:
                compressedData.copy(data);
                if (!crc32OK(data)) {
                    if (async && callback) callback(data, Utils.Errors.BAD_CRC);//si added error
                    return Utils.Errors.BAD_CRC;
                } else {//si added otherwise did not seem to return data.
                    if (async && callback) callback(data);
                    return data;
                }
            case Utils.Constants.DEFLATED:
                var inflater = new Methods.Inflater(compressedData);
                if (!async) {
                    var result = inflater.inflate(data);
                    result.copy(data, 0);
                    if (!crc32OK(data)) {
                        console.warn(Utils.Errors.BAD_CRC + " " + _entryName.toString())
                    }
                    return data;
                } else {
                    inflater.inflateAsync(function(result) {
                        result.copy(data, 0);
                        if (!crc32OK(data)) {
                            if (callback) callback(data, Utils.Errors.BAD_CRC); //si added error
                        } else { //si added otherwise did not seem to return data.
                            if (callback) callback(data);
                        }
                    })
                }
                break;
            default:
                if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD);
                return Utils.Errors.UNKNOWN_METHOD;
        }
    }

    function compress(/*Boolean*/async, /*Function*/callback) {
        if ((!uncompressedData || !uncompressedData.length) && Buffer.isBuffer(input)) {
            // no data set or the data wasn't changed to require recompression
            if (async && callback) callback(getCompressedDataFromZip());
            return getCompressedDataFromZip();
        }

        if (uncompressedData.length && !_isDirectory) {
            var compressedData;
            // Local file header
            switch (_entryHeader.method) {
                case Utils.Constants.STORED:
                    _entryHeader.compressedSize = _entryHeader.size;

                    compressedData = Buffer.alloc(uncompressedData.length);
                    uncompressedData.copy(compressedData);

                    if (async && callback) callback(compressedData);
                    return compressedData;
                default:
                case Utils.Constants.DEFLATED:

                    var deflater = new Methods.Deflater(uncompressedData);
                    if (!async) {
                        var deflated = deflater.deflate();
                        _entryHeader.compressedSize = deflated.length;
                        return deflated;
                    } else {
                        deflater.deflateAsync(function(data) {
                            compressedData = Buffer.alloc(data.length);
                            _entryHeader.compressedSize = data.length;
                            data.copy(compressedData);
                            callback && callback(compressedData);
                        })
                    }
                    deflater = null;
                    break;
            }
        } else {
            if (async && callback) {
                callback(Buffer.alloc(0));
            } else {
                return Buffer.alloc(0);
            }
        }
    }

    function readUInt64LE(buffer, offset) {
        return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
    }

    function parseExtra(data) {
        var offset = 0;
        var signature, size, part;
        while(offset<data.length) {
            signature = data.readUInt16LE(offset);
            offset += 2;
            size = data.readUInt16LE(offset);
            offset += 2;
            part = data.slice(offset, offset+size);
            offset += size;
            if(Constants.ID_ZIP64 === signature) {
                parseZip64ExtendedInformation(part);
            }
        }
    }

    //Override header field values with values from the ZIP64 extra field
    function parseZip64ExtendedInformation(data) {
        var size, compressedSize, offset, diskNumStart;

        if(data.length >= Constants.EF_ZIP64_SCOMP) {
            size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
            if(_entryHeader.size === Constants.EF_ZIP64_OR_32) {
                _entryHeader.size = size;
            }
        }
        if(data.length >= Constants.EF_ZIP64_RHO) {
            compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
            if(_entryHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
                _entryHeader.compressedSize = compressedSize;
            }
        }
        if(data.length >= Constants.EF_ZIP64_DSN) {
            offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
            if(_entryHeader.offset === Constants.EF_ZIP64_OR_32) {
                _entryHeader.offset = offset;
            }
        }
        if(data.length >= Constants.EF_ZIP64_DSN+4) {
            diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
            if(_entryHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
                _entryHeader.diskNumStart = diskNumStart;
            }
        }
    }

    return {
        get entryName () { return _entryName.toString(); },
        get rawEntryName() { return _entryName; },
        set entryName (val) {
            _entryName = Utils.toBuffer(val);
            var lastChar = _entryName[_entryName.length - 1];
            _isDirectory = (lastChar === 47) || (lastChar === 92);
            _entryHeader.fileNameLength = _entryName.length;
        },

        get extra () { return _extra; },
        set extra (val) {
            _extra = val;
            _entryHeader.extraLength = val.length;
            parseExtra(val);
        },

        get comment () { return _comment.toString(); },
        set comment (val) {
            _comment = Utils.toBuffer(val);
            _entryHeader.commentLength = _comment.length;
        },

        get name () { var n = _entryName.toString(); return _isDirectory ? n.substr(n.length - 1).split("/").pop() : n.split("/").pop(); },
        get isDirectory () { return _isDirectory },

        getCompressedData : function() {
            return compress(false, null)
        },

        getCompressedDataAsync : function(/*Function*/callback) {
            compress(true, callback)
        },

        setData : function(value) {
            uncompressedData = Utils.toBuffer(value);
            if (!_isDirectory && uncompressedData.length) {
                _entryHeader.size = uncompressedData.length;
                _entryHeader.method = Utils.Constants.DEFLATED;
                _entryHeader.crc = Utils.crc32(value);
                _entryHeader.changed = true;
            } else { // folders and blank files should be stored
                _entryHeader.method = Utils.Constants.STORED;
            }
        },

        getData : function(pass) {
            if (_entryHeader.changed) {
				return uncompressedData;
			} else {
				return decompress(false, null, pass);
            }
        },

        getDataAsync : function(/*Function*/callback, pass) {
			if (_entryHeader.changed) {
				callback(uncompressedData)
			} else {
				decompress(true, callback, pass)
            }
        },

        set attr(attr) { _entryHeader.attr = attr; },
        get attr() { return _entryHeader.attr; },

        set header(/*Buffer*/data) {
            _entryHeader.loadFromBinary(data);
        },

        get header() {
            return _entryHeader;
        },

        packHeader : function() {
            var header = _entryHeader.entryHeaderToBinary();
            // add
            _entryName.copy(header, Utils.Constants.CENHDR);
            if (_entryHeader.extraLength) {
                _extra.copy(header, Utils.Constants.CENHDR + _entryName.length)
            }
            if (_entryHeader.commentLength) {
                _comment.copy(header, Utils.Constants.CENHDR + _entryName.length + _entryHeader.extraLength, _comment.length);
            }
            return header;
        },

        toString : function() {
            return '{\n' +
                '\t"entryName" : "' + _entryName.toString() + "\",\n" +
                '\t"name" : "' + (_isDirectory ? _entryName.toString().replace(/\/$/, '').split("/").pop() : _entryName.toString().split("/").pop()) + "\",\n" +
                '\t"comment" : "' + _comment.toString() + "\",\n" +
                '\t"isDirectory" : ' + _isDirectory + ",\n" +
                '\t"header" : ' + _entryHeader.toString().replace(/\t/mg, "\t\t").replace(/}/mg, "\t}")  + ",\n" +
                '\t"compressedData" : <' + (input && input.length  + " bytes buffer" || "null") + ">\n" +
                '\t"data" : <' + (uncompressedData && uncompressedData.length  + " bytes buffer" || "null") + ">\n" +
                '}';
        }
    }
};
<|endoftext|>


<commit_before>/*
zoomwall.js

The MIT License (MIT)

Copyright (c) 2014 Eric Leong

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

export var zoomwall = {

  create: function (blocks, enableKeys) {
    const imgs = blocks.querySelectorAll('img');

    zoomwall.resize(imgs);

    blocks.classList.remove('loading');
    // shrink blocks if an empty space is clicked
    blocks.addEventListener('click', function () {
      if (this.children && this.children.length > 0) {
        zoomwall.shrink(this.children[0]);
      }
    });

    // add click listeners to blocks
    imgs.forEach(function(img) {
      img.addEventListener('click', zoomwall.animate);
    });

    // add key down listener
    if (enableKeys) {
      zoomwall.keys(blocks);
    }
  },

  findWall: function(elem) { // traverse dom to find gallery root node
    var parent;

    do {
      parent = elem.parentElement;

      if (parent.classList.contains('zoomwall')) {
        return parent;
      }
    } while (parent);

    return null;
  },

  keys: function (blocks) {
    var keyPager = function (e) {
      if (e.defaultPrevented) {
        return;
      }

      // either use the provided blocks, or query for the first lightboxed zoomwall
      var elem = blocks || document.getElementsByClassName('zoomwall lightbox')[0];

      if (elem) {
        switch (e.keyCode) {
        case 27: // escape
          if (elem.children && elem.children.length > 0) {
            zoomwall.shrink(elem.children[0]);
          }
          e.preventDefault();

          break;

        case 37: // left
          zoomwall.page(elem, false);
          e.preventDefault();

          break;

        case 39: // right
          zoomwall.page(elem, true);
          e.preventDefault();

          break;
        }
      }
    };

    document.addEventListener('keydown', keyPager);

    return keyPager;
  },

  resizeRow: function (row, width) {
    if (row && row.length > 1) {
      for (var i in row) {
        row[i].style.width = (parseInt(window.getComputedStyle(row[i]).width, 10) / width * 100) + '%';
        row[i].style.height = 'auto';
      }
    }
  },

  calcRowWidth: function (row) {
    var width = 0;

    for (var i in row) {
      width += parseInt(window.getComputedStyle(row[i]).width, 10);
    }

    return width;
  },

  resize: function (blocks) {
    var row = [];
    var top = -1;

    for (var c = 0; c < blocks.length; c++) {
      var block = blocks[c];

      if (block) {
        if (top == -1) {
          top = block.offsetTop;

        } else if (block.offsetTop != top) {
          zoomwall.resizeRow(row, zoomwall.calcRowWidth(row));

          row = [];
          top = block.offsetTop;
        }

        row.push(block);
      }
    }

    zoomwall.resizeRow(row, zoomwall.calcRowWidth(row));
  },

  reset: function (block) {
    block.style.transform = 'translate(0, 0) scale(1)';
    block.style.webkitTransform = 'translate(0, 0) scale(1)';
    block.classList.remove('active');
  },

  shrink: function (block) {
    const blocks = zoomwall.findWall(block);

    if (blocks) {
      blocks.classList.remove('lightbox');
    }

    // reset all blocks
    blocks.querySelectorAll('img').forEach(function(img) {
      zoomwall.reset(img);
    });

    // swap images
    if (block.dataset.lowres) {
      block.src = block.dataset.lowres;
    }
    if (block.dataset.sizes) {
      block.sizes = block.dataset.sizes;
    }
  },

  expand: function (block) {

    const blocks = zoomwall.findWall(block);

    block.classList.add('active');
    blocks.classList.add('lightbox');

    // parent dimensions
    var parentStyle = window.getComputedStyle(blocks);

    var parentWidth = parseInt(parentStyle.width, 10);
    var parentHeight = parseInt(parentStyle.height, 10);

    var parentTop = blocks.getBoundingClientRect().top;

    // block dimensions
    var blockStyle = window.getComputedStyle(block);

    var blockWidth = parseInt(blockStyle.width, 10);
    var blockHeight = parseInt(blockStyle.height, 10);

    // determine maximum height
    var targetHeight = window.innerHeight;

    if (parentHeight < window.innerHeight) {
      targetHeight = parentHeight;
    } else if (parentTop > 0) {
      targetHeight -= parentTop;
    }

    // swap images
    if (block.dataset.highres) {
      if (block.src != block.dataset.highres && block.dataset.lowres === undefined) {
        block.dataset.lowres = block.src;
      }
      block.src = block.dataset.highres;
    }
    if (block.sizes) { // responsive images
      block.dataset.sizes = block.sizes;
      block.sizes = '100vw'; // image is now 100% of the viewport width
    }

    // determine what blocks are on this row
    const imgs = blocks.querySelectorAll('img');
    const imgsArray = [...imgs];
    const blockIndex = imgsArray.indexOf(block);

    var row = imgsArray.filter(img => img.offsetTop == block.offsetTop);
    const numBlocksAfterCurrentInRow = row.length - row.indexOf(block) - 1;

    // calculate scale
    var scale = targetHeight / blockHeight;

    if (blockWidth * scale > parentWidth) {
      scale = parentWidth / blockWidth;
    }

    // determine offset
    var offsetY = parentTop - blocks.offsetTop + block.offsetTop;

    if (offsetY > 0) {
      if (parentHeight < window.innerHeight) {
        offsetY -= targetHeight / 2 - blockHeight * scale / 2;
      }

      if (parentTop > 0) {
        offsetY -= parentTop;
      }
    }

    var leftOffsetX = 0;  // shift in current row

    for (var i = 0; i < row.length && row[i] != block; i++) {
      leftOffsetX += parseInt(window.getComputedStyle(row[i]).width, 10) * scale;
    }

    leftOffsetX = parentWidth / 2 - blockWidth * scale / 2 - leftOffsetX;

    var rightOffsetX = 0;  // shift in current row

    for (var j = row.length - 1; j >= 0 && row[j] != block; j--) {
      rightOffsetX += parseInt(window.getComputedStyle(row[j]).width, 10) * scale;
    }

    rightOffsetX = parentWidth / 2 - blockWidth * scale / 2 - rightOffsetX;

    var percentageOffsetX;
    var percentageOffsetY;

    // transform current row
    var itemOffset = 0; // offset due to scaling of previous items
    var prevWidth = 0;

    for (var k = 0; k < row.length; k++) {
      itemOffset += (prevWidth * scale - prevWidth);
      prevWidth = parseInt(window.getComputedStyle(row[k]).width, 10);

      percentageOffsetX = (itemOffset + leftOffsetX) / prevWidth * 100;
      percentageOffsetY = -offsetY / parseInt(window.getComputedStyle(row[k]).height, 10) * 100;

      row[k].style.transformOrigin = '0% 0%';
      row[k].style.webkitTransformOrigin = '0% 0%';
      row[k].style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      row[k].style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }

    // transform items after
    var curTop;
    var nextOffsetY = blockHeight * (scale - 1) - offsetY;
    var prevHeight;
    itemOffset = 0; // offset due to scaling of previous items
    prevWidth = 0;

    var nextRowTop = -1;

    for (let nextItemIndex = blockIndex + numBlocksAfterCurrentInRow + 1, nextItem = imgs[nextItemIndex]; nextItem; nextItem = imgs[++nextItemIndex]) {
      curTop = nextItem.offsetTop;

      if (curTop == nextRowTop) {
        itemOffset += prevWidth * scale - prevWidth;
      } else {

        if (nextRowTop != -1) {
          itemOffset = 0;
          nextOffsetY += prevHeight * (scale - 1);
        }

        nextRowTop = curTop;
      }

      prevWidth = parseInt(window.getComputedStyle(nextItem).width, 10);
      prevHeight = parseInt(window.getComputedStyle(nextItem).height, 10);

      percentageOffsetX = (itemOffset + leftOffsetX) / prevWidth * 100;
      percentageOffsetY = nextOffsetY / prevHeight * 100;

      nextItem.style.transformOrigin = '0% 0%';
      nextItem.style.webkitTransformOrigin = '0% 0%';
      nextItem.style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      nextItem.style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }

    // transform items before
    var prevOffsetY = -offsetY;
    itemOffset = 0; // offset due to scaling of previous items
    prevWidth = 0;

    var prevRowTop = -1;

    for (let prevItemIndex = blockIndex - (row.length - numBlocksAfterCurrentInRow - 1) - 1, prevItem = imgs[prevItemIndex]; prevItem; prevItem = imgs[--prevItemIndex]) {
      curTop = prevItem.offsetTop;

      if (curTop == prevRowTop) {
        itemOffset -= prevWidth * scale - prevWidth;
      } else {
        itemOffset = 0;
        prevOffsetY -= parseInt(window.getComputedStyle(prevItem).height, 10) * (scale - 1);
        prevRowTop = curTop;
      }

      prevWidth = parseInt(window.getComputedStyle(prevItem).width, 10);

      percentageOffsetX = (itemOffset - rightOffsetX) / prevWidth * 100;
      percentageOffsetY = prevOffsetY / parseInt(window.getComputedStyle(prevItem).height, 10) * 100;

      prevItem.style.transformOrigin = '100% 0%';
      prevItem.style.webkitTransformOrigin = '100% 0%';
      prevItem.style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      prevItem.style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }
  },

  animate: function (e) {
    const blocks = zoomwall.findWall(e.target);

    if (this.classList.contains('active')) {
      zoomwall.shrink(this);
    } else {
      var actives = blocks.getElementsByClassName('active');

      for (var i = 0; i < actives.length; i++) {
        actives[i].classList.remove('active');
      }

      zoomwall.expand(this);
    }

    e.stopPropagation();
  },

  page: function (blocks, isNext) {
    var actives = blocks.getElementsByClassName('active');

    if (actives && actives.length > 0) {

      var current = actives[0];
      var next;

      const wall = zoomwall.findWall(current);
      const imgs = wall.querySelectorAll('img');
      const blockIndex = [...imgs].indexOf(current)

      if (isNext) {
        next = imgs[blockIndex + 1];
      } else {
        next = imgs[blockIndex - 1];
      }

      if (next) {
        current.classList.remove('active');
        // swap images
        if (current.dataset.lowres) {
          current.src = current.dataset.lowres;
        }
        if (current.dataset.sizes) {
          current.sizes = current.dataset.sizes;
        }

        zoomwall.expand(next);
      }
    }
  }
};<commit_msg>Declaratively resize rows by grouping them.<commit_after>/*
zoomwall.js

The MIT License (MIT)

Copyright (c) 2014 Eric Leong

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

export var zoomwall = {

  create: function (blocks, enableKeys) {
    const imgs = blocks.querySelectorAll('img');

    zoomwall.resize(imgs);

    blocks.classList.remove('loading');
    // shrink blocks if an empty space is clicked
    blocks.addEventListener('click', function () {
      if (this.children && this.children.length > 0) {
        zoomwall.shrink(this.children[0]);
      }
    });

    // add click listeners to blocks
    imgs.forEach(function(img) {
      img.addEventListener('click', zoomwall.animate);
    });

    // add key down listener
    if (enableKeys) {
      zoomwall.keys(blocks);
    }
  },

  findWall: function(elem) { // traverse dom to find gallery root node
    var parent;

    do {
      parent = elem.parentElement;

      if (parent.classList.contains('zoomwall')) {
        return parent;
      }
    } while (parent);

    return null;
  },

  keys: function (blocks) {
    var keyPager = function (e) {
      if (e.defaultPrevented) {
        return;
      }

      // either use the provided blocks, or query for the first lightboxed zoomwall
      var elem = blocks || document.getElementsByClassName('zoomwall lightbox')[0];

      if (elem) {
        switch (e.keyCode) {
        case 27: // escape
          if (elem.children && elem.children.length > 0) {
            zoomwall.shrink(elem.children[0]);
          }
          e.preventDefault();

          break;

        case 37: // left
          zoomwall.page(elem, false);
          e.preventDefault();

          break;

        case 39: // right
          zoomwall.page(elem, true);
          e.preventDefault();

          break;
        }
      }
    };

    document.addEventListener('keydown', keyPager);

    return keyPager;
  },

  resizeRow: function (row, width) {
    if (row && row.length > 1) {
      row.forEach(function(img) {
        img.style.width = (parseInt(window.getComputedStyle(img).width, 10) / width * 100) + '%';
        img.style.height = 'auto';
      });
    }
  },

  calcRowWidth: function (row) {
    return row.reduce((width, img) => width + parseInt(window.getComputedStyle(img).width, 10), 0);
  },

  resize: function (blocks) {
    [...blocks].reduce(function(rows, block) {
      let offsetTop = block.offsetTop;

      if (!rows.has(offsetTop)) {
        rows.set(offsetTop, [])
      }

      rows.get(offsetTop).push(block);

      return rows;
    }, new Map())
    .forEach(row => zoomwall.resizeRow(row, zoomwall.calcRowWidth(row)));
  },

  reset: function (block) {
    block.style.transform = 'translate(0, 0) scale(1)';
    block.style.webkitTransform = 'translate(0, 0) scale(1)';
    block.classList.remove('active');
  },

  shrink: function (block) {
    const blocks = zoomwall.findWall(block);

    if (blocks) {
      blocks.classList.remove('lightbox');
    }

    // reset all blocks
    blocks.querySelectorAll('img').forEach(function(img) {
      zoomwall.reset(img);
    });

    // swap images
    if (block.dataset.lowres) {
      block.src = block.dataset.lowres;
    }
    if (block.dataset.sizes) {
      block.sizes = block.dataset.sizes;
    }
  },

  expand: function (block) {

    const blocks = zoomwall.findWall(block);

    block.classList.add('active');
    blocks.classList.add('lightbox');

    // parent dimensions
    var parentStyle = window.getComputedStyle(blocks);

    var parentWidth = parseInt(parentStyle.width, 10);
    var parentHeight = parseInt(parentStyle.height, 10);

    var parentTop = blocks.getBoundingClientRect().top;

    // block dimensions
    var blockStyle = window.getComputedStyle(block);

    var blockWidth = parseInt(blockStyle.width, 10);
    var blockHeight = parseInt(blockStyle.height, 10);

    // determine maximum height
    var targetHeight = window.innerHeight;

    if (parentHeight < window.innerHeight) {
      targetHeight = parentHeight;
    } else if (parentTop > 0) {
      targetHeight -= parentTop;
    }

    // swap images
    if (block.dataset.highres) {
      if (block.src != block.dataset.highres && block.dataset.lowres === undefined) {
        block.dataset.lowres = block.src;
      }
      block.src = block.dataset.highres;
    }
    if (block.sizes) { // responsive images
      block.dataset.sizes = block.sizes;
      block.sizes = '100vw'; // image is now 100% of the viewport width
    }

    // determine what blocks are on this row
    const imgs = blocks.querySelectorAll('img');
    const imgsArray = [...imgs];
    const blockIndex = imgsArray.indexOf(block);

    var row = imgsArray.filter(img => img.offsetTop == block.offsetTop);
    const numBlocksAfterCurrentInRow = row.length - row.indexOf(block) - 1;

    // calculate scale
    var scale = targetHeight / blockHeight;

    if (blockWidth * scale > parentWidth) {
      scale = parentWidth / blockWidth;
    }

    // determine offset
    var offsetY = parentTop - blocks.offsetTop + block.offsetTop;

    if (offsetY > 0) {
      if (parentHeight < window.innerHeight) {
        offsetY -= targetHeight / 2 - blockHeight * scale / 2;
      }

      if (parentTop > 0) {
        offsetY -= parentTop;
      }
    }

    var leftOffsetX = 0;  // shift in current row

    for (var i = 0; i < row.length && row[i] != block; i++) {
      leftOffsetX += parseInt(window.getComputedStyle(row[i]).width, 10) * scale;
    }

    leftOffsetX = parentWidth / 2 - blockWidth * scale / 2 - leftOffsetX;

    var rightOffsetX = 0;  // shift in current row

    for (var j = row.length - 1; j >= 0 && row[j] != block; j--) {
      rightOffsetX += parseInt(window.getComputedStyle(row[j]).width, 10) * scale;
    }

    rightOffsetX = parentWidth / 2 - blockWidth * scale / 2 - rightOffsetX;

    var percentageOffsetX;
    var percentageOffsetY;

    // transform current row
    var itemOffset = 0; // offset due to scaling of previous items
    var prevWidth = 0;

    for (var k = 0; k < row.length; k++) {
      itemOffset += (prevWidth * scale - prevWidth);
      prevWidth = parseInt(window.getComputedStyle(row[k]).width, 10);

      percentageOffsetX = (itemOffset + leftOffsetX) / prevWidth * 100;
      percentageOffsetY = -offsetY / parseInt(window.getComputedStyle(row[k]).height, 10) * 100;

      row[k].style.transformOrigin = '0% 0%';
      row[k].style.webkitTransformOrigin = '0% 0%';
      row[k].style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      row[k].style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }

    // transform items after
    var curTop;
    var nextOffsetY = blockHeight * (scale - 1) - offsetY;
    var prevHeight;
    itemOffset = 0; // offset due to scaling of previous items
    prevWidth = 0;

    var nextRowTop = -1;

    for (let nextItemIndex = blockIndex + numBlocksAfterCurrentInRow + 1, nextItem = imgs[nextItemIndex]; nextItem; nextItem = imgs[++nextItemIndex]) {
      curTop = nextItem.offsetTop;

      if (curTop == nextRowTop) {
        itemOffset += prevWidth * scale - prevWidth;
      } else {

        if (nextRowTop != -1) {
          itemOffset = 0;
          nextOffsetY += prevHeight * (scale - 1);
        }

        nextRowTop = curTop;
      }

      prevWidth = parseInt(window.getComputedStyle(nextItem).width, 10);
      prevHeight = parseInt(window.getComputedStyle(nextItem).height, 10);

      percentageOffsetX = (itemOffset + leftOffsetX) / prevWidth * 100;
      percentageOffsetY = nextOffsetY / prevHeight * 100;

      nextItem.style.transformOrigin = '0% 0%';
      nextItem.style.webkitTransformOrigin = '0% 0%';
      nextItem.style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      nextItem.style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }

    // transform items before
    var prevOffsetY = -offsetY;
    itemOffset = 0; // offset due to scaling of previous items
    prevWidth = 0;

    var prevRowTop = -1;

    for (let prevItemIndex = blockIndex - (row.length - numBlocksAfterCurrentInRow - 1) - 1, prevItem = imgs[prevItemIndex]; prevItem; prevItem = imgs[--prevItemIndex]) {
      curTop = prevItem.offsetTop;

      if (curTop == prevRowTop) {
        itemOffset -= prevWidth * scale - prevWidth;
      } else {
        itemOffset = 0;
        prevOffsetY -= parseInt(window.getComputedStyle(prevItem).height, 10) * (scale - 1);
        prevRowTop = curTop;
      }

      prevWidth = parseInt(window.getComputedStyle(prevItem).width, 10);

      percentageOffsetX = (itemOffset - rightOffsetX) / prevWidth * 100;
      percentageOffsetY = prevOffsetY / parseInt(window.getComputedStyle(prevItem).height, 10) * 100;

      prevItem.style.transformOrigin = '100% 0%';
      prevItem.style.webkitTransformOrigin = '100% 0%';
      prevItem.style.transform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
      prevItem.style.webkitTransform = 'translate(' + percentageOffsetX.toFixed(8) + '%, ' + percentageOffsetY.toFixed(8) + '%) scale(' + scale.toFixed(8) + ')';
    }
  },

  animate: function (e) {
    const blocks = zoomwall.findWall(e.target);

    if (this.classList.contains('active')) {
      zoomwall.shrink(this);
    } else {
      var actives = blocks.getElementsByClassName('active');

      for (var i = 0; i < actives.length; i++) {
        actives[i].classList.remove('active');
      }

      zoomwall.expand(this);
    }

    e.stopPropagation();
  },

  page: function (blocks, isNext) {
    var actives = blocks.getElementsByClassName('active');

    if (actives && actives.length > 0) {

      var current = actives[0];
      var next;

      const wall = zoomwall.findWall(current);
      const imgs = wall.querySelectorAll('img');
      const blockIndex = [...imgs].indexOf(current)

      if (isNext) {
        next = imgs[blockIndex + 1];
      } else {
        next = imgs[blockIndex - 1];
      }

      if (next) {
        current.classList.remove('active');
        // swap images
        if (current.dataset.lowres) {
          current.src = current.dataset.lowres;
        }
        if (current.dataset.sizes) {
          current.sizes = current.dataset.sizes;
        }

        zoomwall.expand(next);
      }
    }
  }
};<|endoftext|>