<commit_before>angular.module('anol.map')

/**
 * @ngdoc object
 * @name anol.map.ClusterSelectServiceProvider
 */
.provider('ClusterSelectService', [function() {

    var _clusterSelectOptions;

    this.setClusterSelectOptions = function(options) {
        _clusterSelectOptions = options;
    };

    this.$get = ['MapService', function(MapService) {

        var defaultClusterOptions = {
            selectCluster: true,
            pointRadius: 7,
            spiral: true,
            circleMaxObjects: 10,
            maxObjects: 60,
            animate: true,
            animationDuration: 500,
        };

        var ClusterSelect = function(clusterSelectOptions) {
            this.clusterLayers = [];
            this.selectRevealedFeatureCallbacks = [];
            this.clusterSelectOptions = clusterSelectOptions;
            this.selectedClusterLayer = undefined;
        };

        ClusterSelect.prototype.registerSelectRevealedFeatureCallback = function(f) {
            this.selectRevealedFeatureCallbacks.push(f);
        };

        ClusterSelect.prototype.addLayer = function(layer) {
            var self = this;
            layer.olLayer.on('change:visible', function() {
                if(!layer.getVisible() && layer === self.selectedClusterLayer) {
                    self.selectClusterInteraction.clear();
                }
            });
            this.clusterLayers.push(layer);
        };

        ClusterSelect.prototype.layerByFeature = function(feature) {
            var self = this;
            var resultLayer;
            // TODO collect all anol.layer.Feature into a list
            angular.forEach(self.clusterLayers, function(layer) {
                if(angular.isDefined(resultLayer)) {
                    return;
                }
                if(layer.unclusteredSource.getFeatures().indexOf(feature) > -1) {
                    if(layer instanceof anol.layer.DynamicGeoJSON) {
                        if(feature.get('__layer__') === layer.name) {
                            resultLayer = layer;
                        }
                    } else {
                        resultLayer = layer;
                    }
                }
            });
            return resultLayer;
        };

        ClusterSelect.prototype.getControl = function(recreate) {
            var self = this;
            if(self.clusterLayers.length === 0) {
                return;
            }

            if(angular.isDefined(self.selectClusterControl) && recreate !== true) {
                return self.selectClusterControl;
            }

            var olClusterLayers = [];
            angular.forEach(self.clusterLayers, function(layer) {
                olClusterLayers.push(layer.olLayer);
            });

            var interactionOptions = $.extend({}, defaultClusterOptions, this.clusterSelectOptions, {
                layers: olClusterLayers,
                // for each revealed feature of selected cluster, this function is called
                featureStyle: function(revealedFeature, resolution) {
                    var style = new ol.style.Style();
                    // style link lines
                    if(revealedFeature.get('selectclusterlink') === true) {
                        style = new ol.style.Style({
                            stroke: new ol.style.Stroke({
                                color: '#f00',
                                width: 1
                            })
                        });
                    }
                    if(revealedFeature.get('selectclusterfeature') === true) {
                        var originalFeature = revealedFeature.get('features')[0];
                        var layer = self.layerByFeature(originalFeature);
                        var layerStyle = layer.olLayer.getStyle();

                        if(angular.isFunction(layerStyle)) {
                            layerStyle = layerStyle(originalFeature, resolution)[0];
                        }

                        style = layerStyle;
                    }

                    return [style];
                },
                style: function(clusterFeature, resolution) {
                    if(clusterFeature.get('features').length === 1) {
                        var layer = self.layerByFeature(clusterFeature.get('features')[0]);
                        var style = layer.olLayer.getStyle();
                        if(angular.isFunction(style)) {
                            style = style(clusterFeature, resolution);
                        }
                        if(angular.isArray(style)) {
                            return style;
                        }
                        return [style];
                    }
                    return [new ol.style.Style()];
                }
            });

            var selectedCluster;
            self.selectClusterInteraction = new ol.interaction.SelectCluster(interactionOptions);

            var changeCursorCondition = function(pixel) {
                return MapService.getMap().hasFeatureAtPixel(pixel, function(layer) {
                    var found = false;
                    if(self.selectClusterInteraction.overlayLayer_ === layer) {
                        MapService.getMap().forEachFeatureAtPixel(pixel, function(feature) {
                            if(found) {
                                return;
                            }
                            if(feature.get('selectclusterfeature')) {
                                found = true;
                            }
                        })
                    }
                    return found;
                });
            };

            MapService.addCursorPointerCondition(changeCursorCondition);
            self.selectClusterInteraction.on('select', function(a) {
                if(a.selected.length === 1) {
                    if(a.selected[0].get('features').length > interactionOptions.maxObjects) {
                        var view = MapService.getMap().getView();
                        view.setZoom(view.getZoom() + 1);
                        return;
                    }
                    if(a.selected[0].get('features').length > 1) {
                        selectedCluster = a.selected[0];
                        selectedCluster.setStyle(new ol.style.Style());
                        return;
                    }
                    if(a.selected[0].get('selectclusterfeature') === true) {
                        angular.forEach(self.selectRevealedFeatureCallbacks, function(f) {
                            f(a.selected[0]);
                        });
                    }
                } else if(a.selected.length === 0 && angular.isDefined(selectedCluster)) {
                    selectedCluster.setStyle(null);
                    selectedCluster = undefined;
                }
            });

            self.selectClusterInteraction.getFeatures().on('add', function(e) {
                var features = e.element.get('features');
                var layer = self.layerByFeature(features[0]);
                self.selectedClusterLayer = layer;
                if(angular.isFunction(layer.clusterOptions.onSelect)) {
                    layer.clusterOptions.onSelect(features);
                }
            });

            MapService.getMap().addInteraction(self.selectClusterInteraction);

            self.selectClusterControl = new anol.control.Control({
                subordinate: true,
                olControl: null,
                interactions: [self.selectClusterInteraction]
            });

            var changeCursorCondition = function(pixel) {
                return MapService.getMap().hasFeatureAtPixel(pixel, function(layer) {
                    var anolLayer = layer.get('anolLayer');
                    if(anolLayer === undefined) {
                        return false;
                    }
                    return anolLayer.isClustered();
                });
            };

            self.selectClusterControl.onDeactivate(function() {
                self.selectClusterInteraction.setActive(false);
                MapService.removeCursorPointerCondition(changeCursorCondition);
            });
            self.selectClusterControl.onActivate(function() {
                self.selectClusterInteraction.setActive(true);
                MapService.addCursorPointerCondition(changeCursorCondition);
            });

            // control active by default
            MapService.addCursorPointerCondition(changeCursorCondition);

            return this.selectClusterControl;
        };

        return new ClusterSelect(_clusterSelectOptions);
    }];
}]);<commit_msg>Changed default cluster radius to 10 map units<commit_after>angular.module('anol.map')

/**
 * @ngdoc object
 * @name anol.map.ClusterSelectServiceProvider
 */
.provider('ClusterSelectService', [function() {

    var _clusterSelectOptions;

    this.setClusterSelectOptions = function(options) {
        _clusterSelectOptions = options;
    };

    this.$get = ['MapService', function(MapService) {

        var defaultClusterOptions = {
            selectCluster: true,
            pointRadius: 10,
            spiral: true,
            circleMaxObjects: 10,
            maxObjects: 60,
            animate: true,
            animationDuration: 500
        };

        var ClusterSelect = function(clusterSelectOptions) {
            this.clusterLayers = [];
            this.selectRevealedFeatureCallbacks = [];
            this.clusterSelectOptions = clusterSelectOptions;
            this.selectedClusterLayer = undefined;
        };

        ClusterSelect.prototype.registerSelectRevealedFeatureCallback = function(f) {
            this.selectRevealedFeatureCallbacks.push(f);
        };

        ClusterSelect.prototype.addLayer = function(layer) {
            var self = this;
            layer.olLayer.on('change:visible', function() {
                if(!layer.getVisible() && layer === self.selectedClusterLayer) {
                    self.selectClusterInteraction.clear();
                }
            });
            this.clusterLayers.push(layer);
        };

        ClusterSelect.prototype.layerByFeature = function(feature) {
            var self = this;
            var resultLayer;
            // TODO collect all anol.layer.Feature into a list
            angular.forEach(self.clusterLayers, function(layer) {
                if(angular.isDefined(resultLayer)) {
                    return;
                }
                if(layer.unclusteredSource.getFeatures().indexOf(feature) > -1) {
                    if(layer instanceof anol.layer.DynamicGeoJSON) {
                        if(feature.get('__layer__') === layer.name) {
                            resultLayer = layer;
                        }
                    } else {
                        resultLayer = layer;
                    }
                }
            });
            return resultLayer;
        };

        ClusterSelect.prototype.getControl = function(recreate) {
            var self = this;
            if(self.clusterLayers.length === 0) {
                return;
            }

            if(angular.isDefined(self.selectClusterControl) && recreate !== true) {
                return self.selectClusterControl;
            }

            var olClusterLayers = [];
            angular.forEach(self.clusterLayers, function(layer) {
                olClusterLayers.push(layer.olLayer);
            });

            var interactionOptions = $.extend({}, defaultClusterOptions, this.clusterSelectOptions, {
                layers: olClusterLayers,
                // for each revealed feature of selected cluster, this function is called
                featureStyle: function(revealedFeature, resolution) {
                    var style = new ol.style.Style();
                    // style link lines
                    if(revealedFeature.get('selectclusterlink') === true) {
                        style = new ol.style.Style({
                            stroke: new ol.style.Stroke({
                                color: '#f00',
                                width: 1
                            })
                        });
                    }
                    if(revealedFeature.get('selectclusterfeature') === true) {
                        var originalFeature = revealedFeature.get('features')[0];
                        var layer = self.layerByFeature(originalFeature);
                        var layerStyle = layer.olLayer.getStyle();

                        if(angular.isFunction(layerStyle)) {
                            layerStyle = layerStyle(originalFeature, resolution)[0];
                        }

                        style = layerStyle;
                    }

                    return [style];
                },
                style: function(clusterFeature, resolution) {
                    if(clusterFeature.get('features').length === 1) {
                        var layer = self.layerByFeature(clusterFeature.get('features')[0]);
                        var style = layer.olLayer.getStyle();
                        if(angular.isFunction(style)) {
                            style = style(clusterFeature, resolution);
                        }
                        if(angular.isArray(style)) {
                            return style;
                        }
                        return [style];
                    }
                    return [new ol.style.Style()];
                }
            });

            var selectedCluster;
            self.selectClusterInteraction = new ol.interaction.SelectCluster(interactionOptions);

            var changeCursorCondition = function(pixel) {
                return MapService.getMap().hasFeatureAtPixel(pixel, function(layer) {
                    var found = false;
                    if(self.selectClusterInteraction.overlayLayer_ === layer) {
                        MapService.getMap().forEachFeatureAtPixel(pixel, function(feature) {
                            if(found) {
                                return;
                            }
                            if(feature.get('selectclusterfeature')) {
                                found = true;
                            }
                        })
                    }
                    return found;
                });
            };

            MapService.addCursorPointerCondition(changeCursorCondition);

            self.selectClusterInteraction.on('select', function(a) {
                if(a.selected.length === 1) {
                    if(a.selected[0].get('features').length > interactionOptions.maxObjects) {
                        var view = MapService.getMap().getView();
                        view.setZoom(view.getZoom() + 1);
                        return;
                    }
                    if(a.selected[0].get('features').length > 1) {
                        selectedCluster = a.selected[0];
                        selectedCluster.setStyle(new ol.style.Style());
                        return;
                    }
                    if(a.selected[0].get('selectclusterfeature') === true) {
                        angular.forEach(self.selectRevealedFeatureCallbacks, function(f) {
                            f(a.selected[0]);
                        });
                    }
                } else if(a.selected.length === 0 && angular.isDefined(selectedCluster)) {
                    selectedCluster.setStyle(null);
                    selectedCluster = undefined;
                }
            });

            self.selectClusterInteraction.getFeatures().on('add', function(e) {
                var features = e.element.get('features');
                var layer = self.layerByFeature(features[0]);
                self.selectedClusterLayer = layer;
                if(angular.isFunction(layer.clusterOptions.onSelect)) {
                    layer.clusterOptions.onSelect(features);
                }
            });

            MapService.getMap().addInteraction(self.selectClusterInteraction);

            self.selectClusterControl = new anol.control.Control({
                subordinate: true,
                olControl: null,
                interactions: [self.selectClusterInteraction]
            });

            var changeCursorCondition = function(pixel) {
                return MapService.getMap().hasFeatureAtPixel(pixel, function(layer) {
                    var anolLayer = layer.get('anolLayer');
                    if(anolLayer === undefined) {
                        return false;
                    }
                    return anolLayer.isClustered();
                });
            };

            self.selectClusterControl.onDeactivate(function() {
                self.selectClusterInteraction.setActive(false);
                MapService.removeCursorPointerCondition(changeCursorCondition);
            });
            self.selectClusterControl.onActivate(function() {
                self.selectClusterInteraction.setActive(true);
                MapService.addCursorPointerCondition(changeCursorCondition);
            });

            // control active by default
            MapService.addCursorPointerCondition(changeCursorCondition);

            return this.selectClusterControl;
        };

        return new ClusterSelect(_clusterSelectOptions);
    }];
}]);<|endoftext|>


<commit_before>import {fromJS} from 'immutable';

import {NavigationExperimental} from 'react-native';

const {StateUtils: NavigationStateUtils} = NavigationExperimental;

// Actions
const PUSH_ROUTE = 'NavigationState/PUSH_ROUTE';
const POP_ROUTE = 'NavigationState/POP_ROUTE';
const SWITCH_TAB = 'NavigationState/SWITCH_TAB';

export function switchTab(index) {
  return {
    type: SWITCH_TAB,
    payload: index
  };
}

// Action creators
export function pushRoute(route) {
  return {
    type: PUSH_ROUTE,
    payload: route
  };
}

export function popRoute() {
  return {type: POP_ROUTE};
}

// reducers for tabs and scenes are separate
const initialState = fromJS({
  tabs: {
    index: 0,
    routes: [
      {key: 'LoginTab'},
      {key: 'HomeTab', title: 'RASTIT'},
      {key: 'ProfileTab', title: 'TIIMI'},
      {key: 'MapTab', title: 'MAP'},
      {key: 'LinkTab', title: 'LINKIT'},
    ]
  },

  LoginTab: {
    index: 0,
    routes: [{key: 'Welcome', title: 'Kirjaudu'}]
  },

  // Scenes for the `HomeTab` tab.
  HomeTab: {
    index: 0,
    routes: [{key: 'CheckPoints', title: 'Etusivu'}]
  },

  // Scenes for the `ProfileTab` tab.
  ProfileTab: {
    index: 0,
    routes: [{key: 'TeamView', title: 'Joukkue'}]
  },
  MapTab: {
    index: 0,
    routes: [{key: 'MapView', title: 'Kartta'}]
  },
  LinkTab: {
    index: 0,
    routes: [{key: 'Counter', title: 'Linkit'}]
  },
});

export default function NavigationReducer(state = initialState, action) {
  switch (action.type) {
    case PUSH_ROUTE: {
      // Push a route into the scenes stack.
      const route = action.payload;
      const tabs = state.get('tabs');
      const tabKey = tabs.getIn(['routes', tabs.get('index')]).get('key');
      const scenes = state.get(tabKey).toJS();
      let nextScenes;
      // fixes issue #52
      // the try/catch block prevents throwing an error when the route's key pushed
      // was already present. This happens when the same route is pushed more than once.
      try {
        nextScenes = NavigationStateUtils.push(scenes, route);
      } catch (e) {
        nextScenes = scenes;
      }
      if (scenes !== nextScenes) {
        return state.set(tabKey, fromJS(nextScenes));
      }
      return state;
    }

    case POP_ROUTE: {
      // Pops a route from the scenes stack.
      const tabs = state.get('tabs');
      const tabKey = tabs.getIn(['routes', tabs.get('index')]).get('key');
      const scenes = state.get(tabKey).toJS();
      const nextScenes = NavigationStateUtils.pop(scenes);
      if (scenes !== nextScenes) {
        return state.set(tabKey, fromJS(nextScenes));
      }
      return state;
    }

    case SWITCH_TAB: {
      // Switches the tab.
      const tabs = NavigationStateUtils.jumpToIndex(state.get('tabs').toJS(), action.payload);
      if (tabs !== state.get('tabs')) {
        return state.set('tabs', fromJS(tabs));
      }
      return state;
    }

    default:
      return state;
  }
}
<commit_msg>eslint fixes and navtab names<commit_after>import {fromJS} from 'immutable';

import {NavigationExperimental} from 'react-native';

const {StateUtils: NavigationStateUtils} = NavigationExperimental;

// Actions
const PUSH_ROUTE = 'NavigationState/PUSH_ROUTE';
const POP_ROUTE = 'NavigationState/POP_ROUTE';
const SWITCH_TAB = 'NavigationState/SWITCH_TAB';

export function switchTab(index) {
  return {
    type: SWITCH_TAB,
    payload: index
  };
}

// Action creators
export function pushRoute(route) {
  return {
    type: PUSH_ROUTE,
    payload: route
  };
}

export function popRoute() {
  return {type: POP_ROUTE};
}

// reducers for tabs and scenes are separate
const initialState = fromJS({
  tabs: {
    index: 0,
    routes: [
      {key: 'LoginTab'},
      {key: 'HomeTab', title: 'RASTIT'},
      {key: 'ProfileTab', title: 'TIIMI'},
      {key: 'MapTab', title: 'KARTTA'},
      {key: 'LinkTab', title: 'LINKIT'}
    ]
  },

  LoginTab: {
    index: 0,
    routes: [{key: 'Welcome', title: 'Kirjaudu'}]
  },

  // Scenes for the `HomeTab` tab.
  HomeTab: {
    index: 0,
    routes: [{key: 'CheckPoints', title: 'Etusivu'}]
  },

  // Scenes for the `ProfileTab` tab.
  ProfileTab: {
    index: 0,
    routes: [{key: 'TeamView', title: 'Joukkue'}]
  },
  MapTab: {
    index: 0,
    routes: [{key: 'MapView', title: 'Kartta'}]
  },
  LinkTab: {
    index: 0,
    routes: [{key: 'Counter', title: 'Linkit'}]
  }
});

export default function NavigationReducer(state = initialState, action) {
  switch (action.type) {
    case PUSH_ROUTE: {
      // Push a route into the scenes stack.
      const route = action.payload;
      const tabs = state.get('tabs');
      const tabKey = tabs.getIn(['routes', tabs.get('index')]).get('key');
      const scenes = state.get(tabKey).toJS();
      let nextScenes;
      // fixes issue #52
      // the try/catch block prevents throwing an error when the route's key pushed
      // was already present. This happens when the same route is pushed more than once.
      try {
        nextScenes = NavigationStateUtils.push(scenes, route);
      } catch (e) {
        nextScenes = scenes;
      }
      if (scenes !== nextScenes) {
        return state.set(tabKey, fromJS(nextScenes));
      }
      return state;
    }

    case POP_ROUTE: {
      // Pops a route from the scenes stack.
      const tabs = state.get('tabs');
      const tabKey = tabs.getIn(['routes', tabs.get('index')]).get('key');
      const scenes = state.get(tabKey).toJS();
      const nextScenes = NavigationStateUtils.pop(scenes);
      if (scenes !== nextScenes) {
        return state.set(tabKey, fromJS(nextScenes));
      }
      return state;
    }

    case SWITCH_TAB: {
      // Switches the tab.
      const tabs = NavigationStateUtils.jumpToIndex(state.get('tabs').toJS(), action.payload);
      if (tabs !== state.get('tabs')) {
        return state.set('tabs', fromJS(tabs));
      }
      return state;
    }

    default:
      return state;
  }
}
<|endoftext|>


<commit_before>var
	kind = require('enyo/kind'),
	Control = require('enyo/Control'),
	Group = require('enyo/Group');

var
	FittableRows = require('layout/FittableRows');

var
	Scroller = require('moonstone/Scroller'),
	Divider = require('moonstone/Divider'),
	TooltipDecorator = require('moonstone/TooltipDecorator'),
	Tooltip = require('moonstone/Tooltip'),
	Button = require('moonstone/Button'),
	CaptionDecorator = require('moonstone/CaptionDecorator'),
	ToggleItem = require('moonstone/ToggleItem'),
	BodyText = require('moonstone/BodyText');

module.exports = kind({
	name: 'moon.sample.ButtonSample',
	kind: FittableRows,
	classes: 'moon enyo-unselectable enyo-fit moon-button-sample',
	components: [
		{kind: Scroller, fit: true, components: [
			{kind: Control, classes: 'moon-button-sample-wrapper', components: [

				{kind: Divider, content: 'Buttons:'},
				{kind: TooltipDecorator, components: [
					{name: 'aButton', kind: Button, minWidth: false, content: 'A', ontap: 'buttonTapped'},
					{kind: Tooltip, content: 'minWidth: false'}
				]},
				{kind: TooltipDecorator, components: [
					{name: 'bButton', kind: Button, content: 'B', ontap: 'buttonTapped'},
					{kind: Tooltip, content: 'minWidth: true'}
				]},
				{name: 'button', kind: Button, content: 'Button', uppercase : false, ontap: 'buttonTapped'},
				{name: 'disabledButton', kind: Button, disabled: true, content: 'Disabled Button', ontap: 'buttonTapped'},
				{name: 'longButton', kind: Button, content: 'Looooooooooooooooong Button', ontap: 'buttonTapped'},
				{name: 'spacesButton', kind: Button, content: 'Button   with   extra   spaces', ontap: 'buttonTapped'},
				{kind: Control, tag: 'br'},
				{kind: Control, tag: 'br'},

				{kind: Divider, content: 'Small Buttons:'},
				{name: 'smallAButton', kind: Button, small: true, minWidth: false, content: 'A', ontap: 'buttonTapped'},
				{name: 'smallBButton', kind: Button, small: true, content: 'B', ontap: 'buttonTapped'},
				{name: 'smallButton', kind: Button, small: true, content: 'Button', ontap: 'buttonTapped'},
				{name: 'smallDisabledButton', kind: Button, small: true, disabled: true, content: 'Disabled Button', ontap: 'buttonTapped'},
				{name: 'smallLongButton', kind: Button, small: true, content: 'Loooooooooooooooooooooooong Button', ontap: 'buttonTapped'},
				{name: 'smallSpacesButton', kind: Button, small:true, content: 'Button   with   extra   spaces', ontap: 'buttonTapped'},
				{kind: ToggleItem, classes: 'tap-area-toggle-container', content: 'Show Tap Area', onActivate: 'showSmallButtonTapArea'},
				{kind: Control, tag: 'br'},
				{kind: Control, tag: 'br'},

				{kind: Divider, content: 'Captioned Buttons:'},
				{kind: CaptionDecorator, side: 'top', content: 'Pow', components: [
					{name: 'captionedAButton', kind: Button, content: 'A', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'right', content: 'Boom', components: [
					{name: 'captionedBButton', kind: Button, content: 'B', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'bottom', content: 'Crash', components: [
					{name: 'captionedCButton', kind: Button, content: 'C', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'left', content: 'Bang', components: [
					{name: 'captionedDButton', kind: Button, content: 'D', ontap: 'buttonTapped'}
				]},
				{kind: Control, tag: 'br'},
				{kind: Control, tag: 'br'},

				{kind: Divider, content: 'Captioned Buttons with showOnFocus option:'},
				{kind: CaptionDecorator, side: 'top', showOnFocus: true, content: 'Pow', components: [
					{name: 'showOnFocusCaptionTopButton', kind: Button, content: 'Top', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'bottom', showOnFocus: true, content: 'Crash', components: [
					{name: 'showOnFocusCaptionBottomButton', kind: Button, content: 'Bottom', ontap: 'buttonTapped'}
				]},
				{style: 'display:inline-block;', classes: 'moon-2h'},
				{kind: CaptionDecorator, side: 'left', showOnFocus: true, content: 'Bang', components: [
					{name: 'showOnFocusCaptionLeftButton', kind: Button, content: 'Left', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'right', showOnFocus: true, content: 'Boom', components: [
					{name: 'showOnFocusCaptionRightButton', kind: Button, content: 'Right', ontap: 'buttonTapped'}
				]},
				{kind: Control, tag: 'br'},
				{kind: Control, tag: 'br'},

				{kind: Divider, content: 'Grouped Buttons:'},
				{kind: Group, classes: 'moon-button-sample-group', components: [
					{name: 'appleButton', kind: Button, content: 'Apple', ontap: 'buttonTapped'},
					{name: 'bananaButton', kind: Button, content: 'Banana', ontap: 'buttonTapped'},
					{name: 'saskatoonberryButton', kind: Button, content: 'Saskatoonberry', ontap: 'buttonTapped'}
				]},

				{kind: Divider, content: 'Hidden Buttons:'},
				{name: 'hiddenButton', kind: Button, content: 'Hidden Button', renderOnShow: true, ontap: 'buttonTapped'},
				{name: 'showButton', kind: Button, content: 'Show Hidden Button', ontap: 'showButtonTapped'},

				{kind: Divider, content: 'Translucent Background Buttons:'},
				{classes: 'image-background', components: [
					{name: 'opaqueButton', kind: Button, minWidth: false, content: 'Normal Opaque', ontap: 'buttonTapped'},
					{name: 'translucentButton', kind: Button, minWidth: false, backgroundOpacity: 'translucent', content: 'Translucent', ontap: 'buttonTapped'},
					{name: 'disabledTranslucentButton', kind: Button, minWidth: false, backgroundOpacity: 'translucent', disabled: true, content: 'Disabled Translucent', ontap: 'buttonTapped'},
					{name: 'transparentButton', kind: Button, minWidth: false, backgroundOpacity: 'transparent', content: 'Transparent',  ontap: 'buttonTapped'},
					{name: 'disabledTransparentButton', kind: Button, minWidth: false, backgroundOpacity: 'transparent', disabled: true, content: 'Disabled Transparent',  ontap: 'buttonTapped'}
				]}
			]}
		]},
		{kind: Divider, content: 'Result'},
		{kind: BodyText, name: 'result', allowHtml: true, content: 'No button pressed yet.'}
	],
	buttonTapped: function(inSender, inEvent) {
		this.$.result.setContent('"' + inSender.name + '" pressed.');
	},
	showButtonTapped: function () {
		this.$.hiddenButton.show();
	},
	showSmallButtonTapArea: function(inSender, inEvent) {
		if (inEvent.checked) {
			this.$.smallAButton.addClass('visible-tap-area');
			this.$.smallBButton.addClass('visible-tap-area');
			this.$.smallButton.addClass('visible-tap-area');
			this.$.smallDisabledButton.addClass('visible-tap-area');
			this.$.smallLongButton.addClass('visible-tap-area');
			this.$.smallSpacesButton.addClass('visible-tap-area');
		} else {
			this.$.smallAButton.removeClass('visible-tap-area');
			this.$.smallBButton.removeClass('visible-tap-area');
			this.$.smallButton.removeClass('visible-tap-area');
			this.$.smallDisabledButton.removeClass('visible-tap-area');
			this.$.smallLongButton.removeClass('visible-tap-area');
			this.$.smallSpacesButton.removeClass('visible-tap-area');
		}
	}
});<commit_msg>Added translucent grouped buttons and standardized ButtonSample<commit_after>var
	kind = require('enyo/kind'),
	Group = require('enyo/Group');

var
	FittableRows = require('layout/FittableRows');

var
	Scroller = require('moonstone/Scroller'),
	Divider = require('moonstone/Divider'),
	TooltipDecorator = require('moonstone/TooltipDecorator'),
	Tooltip = require('moonstone/Tooltip'),
	Button = require('moonstone/Button'),
	CaptionDecorator = require('moonstone/CaptionDecorator'),
	ToggleItem = require('moonstone/ToggleItem'),
	BodyText = require('moonstone/BodyText');

module.exports = kind({
	name: 'moon.sample.ButtonSample',
	kind: FittableRows,
	classes: 'moon enyo-unselectable enyo-fit moon-button-sample',
	components: [
		{kind: Scroller, fit: true, components: [
			{classes: 'moon-button-sample-wrapper', components: [

				{kind: Divider, content: 'Buttons:'},
				{kind: TooltipDecorator, components: [
					{name: 'aButton', kind: Button, minWidth: false, content: 'A', ontap: 'buttonTapped'},
					{kind: Tooltip, content: 'minWidth: false'}
				]},
				{kind: TooltipDecorator, components: [
					{name: 'bButton', kind: Button, content: 'B', ontap: 'buttonTapped'},
					{kind: Tooltip, content: 'minWidth: true'}
				]},
				{name: 'button', kind: Button, content: 'Button', uppercase : false, ontap: 'buttonTapped'},
				{name: 'disabledButton', kind: Button, disabled: true, content: 'Disabled Button', ontap: 'buttonTapped'},
				{name: 'longButton', kind: Button, content: 'Looooooooooooooooong Button', ontap: 'buttonTapped'},
				{name: 'spacesButton', kind: Button, content: 'Button   with   extra   spaces', ontap: 'buttonTapped'},
				{classes: 'moon-2v'},

				{kind: Divider, content: 'Small Buttons:'},
				{name: 'smallAButton', kind: Button, small: true, minWidth: false, content: 'A', ontap: 'buttonTapped'},
				{name: 'smallBButton', kind: Button, small: true, content: 'B', ontap: 'buttonTapped'},
				{name: 'smallButton', kind: Button, small: true, content: 'Button', ontap: 'buttonTapped'},
				{name: 'smallDisabledButton', kind: Button, small: true, disabled: true, content: 'Disabled Button', ontap: 'buttonTapped'},
				{name: 'smallLongButton', kind: Button, small: true, content: 'Loooooooooooooooooooooooong Button', ontap: 'buttonTapped'},
				{name: 'smallSpacesButton', kind: Button, small:true, content: 'Button   with   extra   spaces', ontap: 'buttonTapped'},
				{kind: ToggleItem, classes: 'tap-area-toggle-container', content: 'Show Tap Area', onActivate: 'showSmallButtonTapArea'},
				{classes: 'moon-2v'},

				{kind: Divider, content: 'Captioned Buttons:'},
				{kind: CaptionDecorator, side: 'top', content: 'Pow', components: [
					{name: 'captionedAButton', kind: Button, content: 'A', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'right', content: 'Boom', components: [
					{name: 'captionedBButton', kind: Button, content: 'B', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'bottom', content: 'Crash', components: [
					{name: 'captionedCButton', kind: Button, content: 'C', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'left', content: 'Bang', components: [
					{name: 'captionedDButton', kind: Button, content: 'D', ontap: 'buttonTapped'}
				]},
				{classes: 'moon-2v'},

				{kind: Divider, content: 'Captioned Buttons with showOnFocus option:'},
				{kind: CaptionDecorator, side: 'top', showOnFocus: true, content: 'Pow', components: [
					{name: 'showOnFocusCaptionTopButton', kind: Button, content: 'Top', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'bottom', showOnFocus: true, content: 'Crash', components: [
					{name: 'showOnFocusCaptionBottomButton', kind: Button, content: 'Bottom', ontap: 'buttonTapped'}
				]},
				{style: 'display:inline-block;', classes: 'moon-2h'},
				{kind: CaptionDecorator, side: 'left', showOnFocus: true, content: 'Bang', components: [
					{name: 'showOnFocusCaptionLeftButton', kind: Button, content: 'Left', ontap: 'buttonTapped'}
				]},
				{kind: CaptionDecorator, side: 'right', showOnFocus: true, content: 'Boom', components: [
					{name: 'showOnFocusCaptionRightButton', kind: Button, content: 'Right', ontap: 'buttonTapped'}
				]},
				{classes: 'moon-2v'},

				{kind: Divider, content: 'Grouped Buttons:'},
				{kind: Group, classes: 'moon-button-sample-group', components: [
					{name: 'appleButton', kind: Button, content: 'Apple', ontap: 'buttonTapped'},
					{name: 'bananaButton', kind: Button, content: 'Banana', ontap: 'buttonTapped'},
					{name: 'saskatoonberryButton', kind: Button, content: 'Saskatoonberry', ontap: 'buttonTapped'}
				]},
				{classes: 'moon-2v'},

				{kind: Divider, content: 'Hidden Buttons:'},
				{name: 'hiddenButton', kind: Button, content: 'Hidden Button', renderOnShow: true, ontap: 'buttonTapped'},
				{name: 'showButton', kind: Button, content: 'Show Hidden Button', ontap: 'showButtonTapped'},

				{classes: 'moon-2v'},
				{kind: Divider, content: 'Translucent Background Buttons:'},
				{classes: 'image-background', components: [
					{name: 'opaqueButton', kind: Button, minWidth: false, content: 'Normal Opaque', ontap: 'buttonTapped'},
					{name: 'translucentButton', kind: Button, minWidth: false, backgroundOpacity: 'translucent', content: 'Translucent', ontap: 'buttonTapped'},
					{name: 'disabledTranslucentButton', kind: Button, minWidth: false, backgroundOpacity: 'translucent', disabled: true, content: 'Disabled Translucent', ontap: 'buttonTapped'},
					{name: 'transparentButton', kind: Button, minWidth: false, backgroundOpacity: 'transparent', content: 'Transparent',  ontap: 'buttonTapped'},
					{name: 'disabledTransparentButton', kind: Button, minWidth: false, backgroundOpacity: 'transparent', disabled: true, content: 'Disabled Transparent',  ontap: 'buttonTapped'},
					{classes: 'moon-1v'},
					{kind: Divider, content: 'Grouped Buttons:'},
					{kind: Group, classes: 'moon-button-sample-group', components: [
						{name: 'appleButton2', kind: Button, content: 'Apple', backgroundOpacity: 'translucent', ontap: 'buttonTapped'},
						{name: 'bananaButton2', kind: Button, content: 'Banana', backgroundOpacity: 'translucent', ontap: 'buttonTapped'},
						{name: 'saskatoonberryButton2', kind: Button, content: 'Saskatoonberry', backgroundOpacity: 'translucent', ontap: 'buttonTapped'}
					]}
				]}
			]}
		]},
		{kind: Divider, content: 'Result'},
		{kind: BodyText, name: 'result', allowHtml: true, content: 'No button pressed yet.'}
	],
	buttonTapped: function(inSender, inEvent) {
		this.$.result.setContent('"' + inSender.name + '" pressed.');
	},
	showButtonTapped: function () {
		this.$.hiddenButton.show();
	},
	showSmallButtonTapArea: function(inSender, inEvent) {
		if (inEvent.checked) {
			this.$.smallAButton.addClass('visible-tap-area');
			this.$.smallBButton.addClass('visible-tap-area');
			this.$.smallButton.addClass('visible-tap-area');
			this.$.smallDisabledButton.addClass('visible-tap-area');
			this.$.smallLongButton.addClass('visible-tap-area');
			this.$.smallSpacesButton.addClass('visible-tap-area');
		} else {
			this.$.smallAButton.removeClass('visible-tap-area');
			this.$.smallBButton.removeClass('visible-tap-area');
			this.$.smallButton.removeClass('visible-tap-area');
			this.$.smallDisabledButton.removeClass('visible-tap-area');
			this.$.smallLongButton.removeClass('visible-tap-area');
			this.$.smallSpacesButton.removeClass('visible-tap-area');
		}
	}
});<|endoftext|>


<commit_before>var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

exports.assetsPath = function (_path) {
  var assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory
  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function (options) {
  options = options || {}

  var cssLoader = {
    loader: 'css-loader',
    options: {
      minimize: process.env.NODE_ENV === 'production',
      sourceMap: options.sourceMap
    }
  }

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader) {
    var loaders = [cssLoader]
    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: {
          sourceMap: options.sourceMap
        }
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass?indentedSyntax'),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
  var output = []
  var loaders = exports.cssLoaders(options)
  for (var extension in loaders) {
    var loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }
  return output
}
<commit_msg>fix lang="sass"<commit_after>var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

exports.assetsPath = function (_path) {
  var assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory
  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function (options) {
  options = options || {}

  var cssLoader = {
    loader: 'css-loader',
    options: {
      minimize: process.env.NODE_ENV === 'production',
      sourceMap: options.sourceMap
    }
  }

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    var loaders = [cssLoader]
    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
  var output = []
  var loaders = exports.cssLoaders(options)
  for (var extension in loaders) {
    var loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }
  return output
}
<|endoftext|>


<commit_before>(function() {

    var methods = {
        siblings: function() {
            var matched = [];
            this.forEach(function(elem) {
                matched = matched.concat([...elem.parentElement.children].filter(c => c.nodeType == 1 && c != elem));
            });

            return matched;
        },

        attr: function(attributes) {
            // Don't get/set attributes on text, comment and attribute nodes
            if (this.nodeType === 3 || this.nodeType === 8 || this.nodeType === 2) {
                return this;
            }

            if (attributes instanceof Object) {
                for (var key in attributes) {
                    this.setAttribute(key, attributes[key]);
                }
                return this;
            } else {
                return this.getAttribute(attributes);
            }
        },

        css: function(styles) {
            if (this.nodeType === 1) {
                for (var key in styles) {
                    this.style[key] = styles[key];
                }
            }

            return this;
        },

        parents: function() {
            var matched = [];
            this.forEach(function(elem) {
                while (elem) {
                    if (elem.nodeType === 9) {
                        break;
                    }

                    if (elem.nodeType === 1) {
                        if (matched.indexOf(elem) === -1) {
                            matched.push(elem);
                        }
                    }

                    elem = elem.parentNode;
                }
            });

            return matched;
        },

        closest: function(selector) {
            var matched = [];
            this.forEach(elem => matched.push(elem.closest(selector)));

            return matched;
        },

        hasClass: function(selector) {
            var classes = this.getAttribute && this.getAttribute("class") || "",
                className = " " + selector + " ";
            if (this.nodeType === 1 && (" " + classes + " ").indexOf(className) > -1) {
                return true;
            }

            return false;
        },

        readable: function() {
            if (this.length === 0) return;

            var parents = this.parents();

            this.forEach(function(elem) {
                while (elem && elem.tagName.toUpperCase() !== 'BODY') {
                    var $elem = $(elem);
                    $elem.css({
                        padding: 0,
                        margin: '0 auto',
                        minWidth: '1024px',
                        width: '1024px',
                        position: 'static'
                    });

                    $elem.siblings().filter(function(elem) {
                        if (elem.tagName.toUpperCase() === 'LINK') {
                            return false;
                        }
                        if (parents.indexOf(elem) > -1) {
                            return false;
                        }
                        return true;
                    }).remove();

                    elem = elem.parentNode;
                }
            });

            $(this).css({
                padding: '15px',
                boxSizing: 'border-box'
            });

            var body = document.body,
                html = document.documentElement;
            document.body.style.height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);

            return this;
        },

        prepend: function() {
            [...arguments].forEach(elem => {
                $(elem).forEach(e => this.insertBefore(e, this.firstElementChild));
            });

            return this;
        },

        remove: function() {
            this.forEach(function(elem) {
                if (elem instanceof Node) {
                    elem.remove();
                }
            });

            return this;
        }

    };

    // transform object of Node/NodeList/Array to enhanced Array instance
    var $ = function(array) {
        var attr = {};

        if (!arguments.length) {
            array = [];
        } else if (array instanceof Node) {
            array = [array];
        } else if (array instanceof NodeList) {
            array = [...array];
        } else if (array instanceof HTMLCollection) {
            array = [...array];
        }

        ['filter', 'map', 'slice', 'sort'].forEach(function(method) {
            attr[method] = {
                value: function() {
                    var array = Array.prototype[method].apply(this, arguments);
                    return $(array);
                },
                enumerable: false
            };
        });
        ("blur focus focusin focusout resize scroll click dblclick " +
            "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
            "change select submit keydown keypress keyup").split(" ").forEach(function(event) {
            attr[event] = {
                value: function() {
                    this.forEach(elem => {
                        if (arguments.length) {
                            [...arguments].forEach((fn) => {
                                elem.addEventListener(event, fn, false);
                            });
                        } else {
                            elem[event]();
                        }
                    });

                    return this;
                },
                enumerable: false
            };
        });
        attr.first = {
            value: function() {
                var array = Array.prototype.slice.call(this, 0, 1);
                return $(array);
            },
            enumerable: false
        };
        attr.last = {
            value: function() {
                var array = Array.prototype.slice.call(this, this.length - 1, this.length);
                return $(array);
            },
            enumerable: false
        };
        attr.remove = {
            value: function() {
                var array = methods.remove.apply(this, arguments);
                return $(array);
            },
            enumerable: false
        };
        attr.readable = {
            value: function() {
                return methods.readable.apply(this, arguments);
            },
            enumerable: false
        };
        attr.siblings = {
            value: function() {
                var array = methods.siblings.apply(this, arguments);
                return $(array);
            },
            enumerable: false
        };
        attr.parents = {
            value: function() {
                var array = methods.parents.apply(this, arguments);
                return $(array);
            },
            enumerable: false
        };
        attr.closest = {
            value: function() {
                var array = methods.closest.apply(this, arguments);
                return $(array);
            },
            enumerable: false
        };
        attr.hasClass = {
            value: function() {
                this.forEach(elem => {
                    if (!methods.hasClass.apply(elem, arguments)) return false;
                });
                return true;
            },
            enumerable: false
        };
        attr.attr = {
            value: function() {
                if (arguments.length) {
                    if (arguments[0] instanceof Object) {
                        this.forEach(elem => methods.attr.apply(elem, arguments));
                    } else {
                        var values = [];
                        this.forEach(elem => values.push(methods.attr.apply(elem, arguments)));
                        return values;
                    }
                }
                return this;
            },
            enumerable: false
        };
        attr.css = {
            value: function() {
                this.forEach(elem => methods.css.apply(elem, arguments));
                return this;
            },
            enumerable: false
        };
        attr.prepend = {
            value: function() {
                this.forEach(elem => methods.prepend.apply(elem, arguments));
                return this;
            },
            enumerable: false
        };

        return Object.create(array, attr);
    };

    Object.defineProperty(Document.prototype, '$', {
        get() {
            return function() {
                if (arguments.length === 0) {
                    return $(document);
                } else if (!(arguments[0] instanceof Object)) {
                    return $(document.querySelectorAll.apply(document, arguments));
                } else {
                    return $(arguments[0]);
                }
            };
        },
        enumerable: false
    });

    Object.defineProperty(NodeList.prototype, '$', {
        get() {
            return $(this);
        },
        enumerable: false
    });

})();<commit_msg>update d.js<commit_after>(function() {

    var element = {
        siblings: function() {
            return [...this.parentElement.children].filter(c => c.nodeType == 1 && c != this);
        },
        attr: function(attributes) {
            if (this.nodeType === 3 || this.nodeType === 8 || this.nodeType === 2) {
                return this;
            }

            if (typeof attributes === 'string') {
                return this.getAttribute(attributes);
            } else {
                for (var key in attributes) {
                    this.setAttribute(key, attributes[key]);
                }
                return this;
            }
        },
        css: function(styles) {
            if (this.nodeType === 1) {
                for (var key in styles) {
                    this.style[key] = styles[key];
                }
            }

            return this;
        },
        parents: function() {
            var matched = [],
                elem = this;
            while (elem) {
                if (elem.nodeType === 9) {
                    break;
                }

                if (elem.nodeType === 1) {
                    if (matched.indexOf(elem) === -1) {
                        matched.push(elem);
                    }
                }

                elem = elem.parentNode;
            }

            return matched;
        },
        hasClass: function(selector) {
            var classes = this.getAttribute && this.getAttribute("class") || "",
                className = " " + selector + " ";
            if (this.nodeType === 1 && (" " + classes + " ").indexOf(className) > -1) {
                return true;
            }

            return false;
        },
        prepend: function() {
            [...arguments].forEach(elem => {
                $(elem).forEach(e => this.insertBefore(e, this.firstElementChild));
            });

            return this;
        }
    };

    // transform object of Node/NodeList/Array to enhanced Array instance
    var $ = function(array) {
        var attr = {};

        if (!arguments.length) {
            array = [];
        } else if (array instanceof Node) {
            array = [array];
        } else if (array instanceof NodeList) {
            array = [...array];
        } else if (array instanceof HTMLCollection) {
            array = [...array];
        }

        ['filter', 'map', 'slice', 'sort'].forEach(function(method) {
            attr[method] = {
                value: function() {
                    var array = Array.prototype[method].apply(this, arguments);
                    return $(array);
                },
                enumerable: false
            };
        });
        ("blur focus focusin focusout resize scroll click dblclick " +
            "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
            "change select submit keydown keypress keyup").split(" ").forEach(function(event) {
            attr[event] = {
                value: function() {
                    this.forEach(elem => {
                        if (arguments.length) {
                            [...arguments].forEach((fn) => {
                                elem.addEventListener(event, fn, false);
                            });
                        } else {
                            elem[event]();
                        }
                    });

                    return this;
                },
                enumerable: false
            };
        });
        attr.first = {
            value: function() {
                var array = Array.prototype.slice.call(this, 0, 1);
                return $(array);
            },
            enumerable: false
        };
        attr.last = {
            value: function() {
                var array = Array.prototype.slice.call(this, this.length - 1, this.length);
                return $(array);
            },
            enumerable: false
        };
        attr.remove = {
            value: function() {
                this.forEach(function(elem) {
                    if (elem.nodeType === 1) {
                        elem.remove();
                    }
                });
                return this;
            },
            enumerable: false
        };
        attr.siblings = {
            value: function() {
                var array = [];
                this.forEach(function(elem) {
                    array = array.concat(element.siblings.apply(elem, arguments));
                });

                return $(array);
            },
            enumerable: false
        };
        attr.parents = {
            value: function() {
                var array = [];
                this.forEach(function(elem) {
                    element.parents.apply(elem, arguments).forEach(function(p) {
                        if (array.indexOf(p) === -1) {
                            array.push(p);
                        }
                    });
                });
                return $(array);
            },
            enumerable: false
        };
        attr.closest = {
            value: function(selector) {
                var array = [];
                this.forEach(elem => array.push(elem.closest(selector)));
                return $(array);
            },
            enumerable: false
        };
        attr.hasClass = {
            value: function() {
                this.forEach(elem => {
                    if (!element.hasClass.apply(elem, arguments)) return false;
                });
                return true;
            },
            enumerable: false
        };
        attr.attr = {
            value: function() {
                if (arguments.length) {
                    if (typeof arguments[0] === 'string') {
                        var values = [];
                        this.forEach(elem => values.push(element.attr.apply(elem, arguments)));
                        if (values.length === 1) {
                            return values[0];
                        }
                        return values;
                    } else {
                        this.forEach(elem => element.attr.apply(elem, arguments));
                    }
                }
                return this;
            },
            enumerable: false
        };
        attr.css = {
            value: function() {
                this.forEach(elem => element.css.apply(elem, arguments));
                return this;
            },
            enumerable: false
        };
        // attr.after
        // attr.before
        // attr.append
        // attr.parent
        // attr.addClass
        // attr.removeClass
        // attr.hide
        // attr.show
        // attr.val
        attr.prepend = {
            value: function() {
                this.forEach(elem => element.prepend.apply(elem, arguments));
                return this;
            },
            enumerable: false
        };
        attr.querySelectorAll = {
            value: function(selector) {
                if (typeof selector === 'string') {
                    var array = [];
                    this.forEach(function(elem) {
                        var subs = elem.querySelectorAll(selector);
                        array.push(...subs);
                    });
                    return $(array);
                } else {
                    return $(selector);
                }
            },
            enumerable: false
        };
        attr.readable = {
            value: function() {
                if (this.length === 0) return;

                var parents = this.parents();

                this.forEach(function(elem) {
                    while (elem && elem.tagName.toUpperCase() !== 'BODY') {
                        var $elem = $(elem);
                        $elem.css({
                            padding: 0,
                            margin: '0 auto',
                            minWidth: '1024px',
                            width: '1024px',
                            position: 'static'
                        });

                        $elem.siblings().filter(function(elem) {
                            if (elem.tagName.toUpperCase() === 'LINK') {
                                return false;
                            }
                            if (parents.indexOf(elem) > -1) {
                                return false;
                            }
                            return true;
                        }).remove();

                        elem = elem.parentNode;
                    }
                });

                $(this).css({
                    padding: '15px',
                    boxSizing: 'border-box'
                });

                var body = document.body,
                    html = document.documentElement;
                document.body.style.height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);

                return this;
            },
            enumerable: false
        };

        return Object.create(array, attr);
    };

    Object.defineProperty(Document.prototype, '$', {
        get() {
            return function() {
                if (arguments.length === 0) {
                    return $(document);
                } else if (!(arguments[0] instanceof Object)) {
                    return $(document.querySelectorAll.apply(document, arguments));
                } else {
                    return $(arguments[0]);
                }
            };
        },
        enumerable: false
    });

    Object.defineProperty(NodeList.prototype, '$', {
        get() {
            return $(this);
        },
        enumerable: false
    });

})();<|endoftext|>


<commit_before>// @flow

import map from 'lodash/map';
import groupBy from 'lodash/groupBy';
import getCollectionProp from './getCollectionProp';

/**
* It returns grouped results
* @param  {string} prop    grouping result by this object key
* @param  {function} [labelIteratee = (records, field) => field]
* group field value format method. Default return original value
* @param  {function} [valueIteratee = (records, field) => records.length]
* group field items method. Default is count group elements
* @return {object}          {'group1': valueIteratee return, 'group2': valueIteratee return}
*
* @example
* Grouping by date, where the value sum every record person property
* [{date: '2016-02-03', person: '3'}...]
* // => {'2016-02-03': 22, '2016-02-04': 25 }
* collectionGroupBy(data, 'date', (value, key) => (sum(map(value, i => parseInt(i.person)))))
*/
export const collectionGroupBy = (
  data: Array<{}>,
  prop: string,
  labelIteratee?: (groupRecords: Array<{}>, groupProp: string) => string
    = (groupRecords, groupProp) => groupProp,
  valueIteratee?: (groupRecords: Array<{}>, groupProp: string) => number
    = groupRecords => groupRecords.length,
): Array<{ id: string, title: number }> =>
{
  return map(
    groupBy(data, x => x[prop]),
    (groupRecords, groupProp) =>
    ({
      id: labelIteratee(groupRecords, groupProp),
      title: valueIteratee(groupRecords, groupProp),
    }),
  );
};

/**
 * Collect collection and count data
 *
 * @since 3.9.0
 * @static
 * @memberof array
 * @param  {array} data collection
 * @param  {string} prop field of record within collection
 * @param  {func} method accumulator (ex. sum, mean, count ...)
 * @param  {string|array} group multidimension results
 * @return {object}
 * @example
 * pivotTable(data, 'gender', count),
 * // => 12
 *
 * pivotTable(data, 'gender', values => values.length),
 * // => 12
 *
 * pivotTable(data, 'gender', countUnique),
 * // => 2
 *
 * // collectionGroupBy(data, 'gender'),
 * // => [ { id: '1', title: 8 }, { id: '2', title: 4 } ]
 *
 * pivotTable(data, 'gender', count, 'gender'),
 * // => [ { id: '1', title: 8 }, { id: '2', title: 4 }, { id: 'count', title: 12 } ]
 *
 * pivotTable(data, 'age', mean, 'visits'),
 * // => { id: '2017-07-23', title: 22 }, { id: '2017-07-22', title: 28.666666666666668 } ...,
 *
 * pivotTable(data, 'age', mean, ['visits', 'gender']),
 * // => { id: '2017-07-23', title: [ { id: '1', title: 8 }, { id: '2', title: 4 }, { id: 'mean', title: 12 } ] }, ...
 *
 * pivotTable(data, mean),
 * // => { id: 6.5, name: NaN, gender: 1.3333333333333333, age: 26.5, visits: NaN }
 *
 */
const pivotTable2 = function (data: Array<{}>, prop?: string|Function, method?: Function, group?: string)
{
  if (typeof prop === 'undefined' || Array.isArray(data) === false)
  {
    return null;
  }

  let result;

  if (typeof prop === 'string' && typeof method === 'function')
  {
    let results = [];

    if (group)
    {
      const groups = Array.isArray(group) ? group : [group];
      let groupsIndex = 0;

      const groupDataIterator = (groupData) =>
      {
        groupsIndex++;

        const groupResult = method(getCollectionProp(groupData, prop));

        let child;

        if (groupsIndex < groups.length)
        {
          child = collectionGroupBy(groupData, groups[groupsIndex], undefined, groupDataIterator);
        }

        groupsIndex -= 1;

        if (child)
        {
          child.push({
            id: '_result',
            title: groupResult,
          });

          return child;
        }

        return groupResult;
      }

      /**
       * Collect data by group props. Iterate groups and call method every group
       * @type {array} [{ id: 'male', title: 2 }, { id: 'male', title: 2 }]
       * id: group field value,
       * title: calculated method results (ex. count, sum, mean ...)
       */
      results = collectionGroupBy(
        data,
        groups[0],
        undefined,
        groupDataIterator,
      );
    }

    /**
     * @example
     * // => [1,2,1,1,1,2,1]
     */
    const values = getCollectionProp(data, prop);

    results.push({
      id: method.name || 'result',
      title: values.length ? method(values) : 0,
    });

    result = (results.length === 1) ? results[0].title : results;
  }
  else if (typeof prop === 'function')
  {
    const method = prop;
    const columns = Object.keys(data[0]);

    result = columns.reduce(
      (results, column) => ({
        ...results,
        [column]: pivotTable(data, column, method),
      }),
      {},
    );
  }

  // if (this instanceof pivotTable)
  if (this)
  {
    this.result = result;
  }

  return result;
}

const pivotTable = function (data: Array<{}>, prop?: string|Function, method?: Function, group?: string|Array<string>)
{
  if (typeof prop === 'undefined' || Array.isArray(data) === false)
  {
    return null;
  }

  let result;

  if (typeof prop === 'string' && typeof method === 'function')
  {
    let results = [];

    if (group)
    {
      const groups = Array.isArray(group) ? group : [group];
      let groupsIndex = 0;

      const groupDataIterator = (groupData) =>
      {
        groupsIndex++;

        const groupResult = method(getCollectionProp(groupData, prop));

        let child;

        if (groupsIndex < groups.length)
        {
          child = collectionGroupBy(groupData, groups[groupsIndex], undefined, groupDataIterator);
        }

        groupsIndex--;

        if (child)
        {
          child.push({
            id: method.name || 'result',
            title: groupResult,
          });

          return child;
        }

        return groupResult;
      }

      /**
       * Collect data by group props. Iterate groups and call method every group
       * @type {array} [{ id: 'male', title: 2 }, { id: 'male', title: 2 }]
       * id: group field value,
       * title: calculated method results (ex. count, sum, mean ...)
       */
      results = collectionGroupBy(
        data,
        groups[0],
        undefined,
        groupDataIterator,
      );
    }

    /**
     * @example
     * // => [1,2,1,1,1,2,1]
     */
    const values = getCollectionProp(data, prop);

    results.push({
      id: method.name || 'result',
      title: values.length ? method(values) : 0,
    });

    result = (results.length === 1) ? results[0].title : results;
  }
  else if (typeof prop === 'function')
  {
    const method = prop;
    const columns = Object.keys(data[0]);

    result = columns.reduce(
      (results, column) => ({
        ...results,
        [column]: pivotTable(data, column, method),
      }),
      {},
    );
  }

  if (this instanceof pivotTable)
  {
    this.result = result;
    return;
  }

   return result;
}

pivotTable.prototype =
{
  /**
   * Convert pivotTable data to collection
   * @example
   * { id: '2017-07-23', title: [ { id: 'male', title: 8 }, { id: 'female', title: 4 }, { id: 'count', title: 12 } ] }
   * // => [{ id, male, femail, count }, ... ]
   */
  toArray: function(transform)
  {
    if (!this.result)
    {
      return [];
    }

    return this.result.map(({ id, title }) =>
    {
      const record = {id};

      if (Array.isArray(title))
      {
        title.forEach(child => record[child.id] = child.title);
      }
      else
      {
        record[id] = title;
      }

      return typeof transform === 'function' ? transform(record) : record;
    });
  },
};

export default pivotTable;
<commit_msg>Revert "fix(array): picotTable"<commit_after>// @flow

import map from 'lodash/map';
import groupBy from 'lodash/groupBy';
import getCollectionProp from './getCollectionProp';

/**
* It returns grouped results
* @param  {string} prop    grouping result by this object key
* @param  {function} [labelIteratee = (records, field) => field]
* group field value format method. Default return original value
* @param  {function} [valueIteratee = (records, field) => records.length]
* group field items method. Default is count group elements
* @return {object}          {'group1': valueIteratee return, 'group2': valueIteratee return}
*
* @example
* Grouping by date, where the value sum every record person property
* [{date: '2016-02-03', person: '3'}...]
* // => {'2016-02-03': 22, '2016-02-04': 25 }
* collectionGroupBy(data, 'date', (value, key) => (sum(map(value, i => parseInt(i.person)))))
*/
export const collectionGroupBy = (
  data: Array<{}>,
  prop: string,
  labelIteratee?: (groupRecords: Array<{}>, groupProp: string) => string
    = (groupRecords, groupProp) => groupProp,
  valueIteratee?: (groupRecords: Array<{}>, groupProp: string) => number
    = groupRecords => groupRecords.length,
): Array<{ id: string, title: number }> =>
{
  return map(
    groupBy(data, x => x[prop]),
    (groupRecords, groupProp) =>
    ({
      id: labelIteratee(groupRecords, groupProp),
      title: valueIteratee(groupRecords, groupProp),
    }),
  );
};

/**
 * Collect collection and count data
 *
 * @since 3.9.0
 * @static
 * @memberof array
 * @param  {array} data collection
 * @param  {string} prop field of record within collection
 * @param  {func} method accumulator (ex. sum, mean, count ...)
 * @param  {string|array} group multidimension results
 * @return {object}
 * @example
 * pivotTable(data, 'gender', count),
 * // => 12
 *
 * pivotTable(data, 'gender', values => values.length),
 * // => 12
 *
 * pivotTable(data, 'gender', countUnique),
 * // => 2
 *
 * // collectionGroupBy(data, 'gender'),
 * // => [ { id: '1', title: 8 }, { id: '2', title: 4 } ]
 *
 * pivotTable(data, 'gender', count, 'gender'),
 * // => [ { id: '1', title: 8 }, { id: '2', title: 4 }, { id: 'count', title: 12 } ]
 *
 * pivotTable(data, 'age', mean, 'visits'),
 * // => { id: '2017-07-23', title: 22 }, { id: '2017-07-22', title: 28.666666666666668 } ...,
 *
 * pivotTable(data, 'age', mean, ['visits', 'gender']),
 * // => { id: '2017-07-23', title: [ { id: '1', title: 8 }, { id: '2', title: 4 }, { id: 'mean', title: 12 } ] }, ...
 *
 * pivotTable(data, mean),
 * // => { id: 6.5, name: NaN, gender: 1.3333333333333333, age: 26.5, visits: NaN }
 *
 */
const pivotTable2 = function (data: Array<{}>, prop?: string|Function, method?: Function, group?: string)
{
  if (typeof prop === 'undefined' || Array.isArray(data) === false)
  {
    return null;
  }

  let result;

  if (typeof prop === 'string' && typeof method === 'function')
  {
    let results = [];

    if (group)
    {
      const groups = Array.isArray(group) ? group : [group];
      let groupsIndex = 0;

      const groupDataIterator = (groupData) =>
      {
        groupsIndex++;

        const groupResult = method(getCollectionProp(groupData, prop));

        let child;

        if (groupsIndex < groups.length)
        {
          child = collectionGroupBy(groupData, groups[groupsIndex], undefined, groupDataIterator);
        }

        groupsIndex -= 1;

        if (child)
        {
          child.push({
            id: method.name || 'result',
            title: groupResult,
          });

          return child;
        }

        return groupResult;
      }

      /**
       * Collect data by group props. Iterate groups and call method every group
       * @type {array} [{ id: 'male', title: 2 }, { id: 'male', title: 2 }]
       * id: group field value,
       * title: calculated method results (ex. count, sum, mean ...)
       */
      results = collectionGroupBy(
        data,
        groups[0],
        undefined,
        groupDataIterator,
      );
    }

    /**
     * @example
     * // => [1,2,1,1,1,2,1]
     */
    const values = getCollectionProp(data, prop);

    results.push({
      id: method.name || 'result',
      title: values.length ? method(values) : 0,
    });

    result = (results.length === 1) ? results[0].title : results;
  }
  else if (typeof prop === 'function')
  {
    const method = prop;
    const columns = Object.keys(data[0]);

    result = columns.reduce(
      (results, column) => ({
        ...results,
        [column]: pivotTable(data, column, method),
      }),
      {},
    );
  }

  // if (this instanceof pivotTable)
  if (this)
  {
    this.result = result;
  }

  return result;
}

const pivotTable = function (data: Array<{}>, prop?: string|Function, method?: Function, group?: string|Array<string>)
{
  if (typeof prop === 'undefined' || Array.isArray(data) === false)
  {
    return null;
  }

  let result;

  if (typeof prop === 'string' && typeof method === 'function')
  {
    let results = [];

    if (group)
    {
      const groups = Array.isArray(group) ? group : [group];
      let groupsIndex = 0;

      const groupDataIterator = (groupData) =>
      {
        groupsIndex++;

        const groupResult = method(getCollectionProp(groupData, prop));

        let child;

        if (groupsIndex < groups.length)
        {
          child = collectionGroupBy(groupData, groups[groupsIndex], undefined, groupDataIterator);
        }

        groupsIndex--;

        if (child)
        {
          child.push({
            id: method.name || 'result',
            title: groupResult,
          });

          return child;
        }

        return groupResult;
      }

      /**
       * Collect data by group props. Iterate groups and call method every group
       * @type {array} [{ id: 'male', title: 2 }, { id: 'male', title: 2 }]
       * id: group field value,
       * title: calculated method results (ex. count, sum, mean ...)
       */
      results = collectionGroupBy(
        data,
        groups[0],
        undefined,
        groupDataIterator,
      );
    }

    /**
     * @example
     * // => [1,2,1,1,1,2,1]
     */
    const values = getCollectionProp(data, prop);

    results.push({
      id: method.name || 'result',
      title: values.length ? method(values) : 0,
    });

    result = (results.length === 1) ? results[0].title : results;
  }
  else if (typeof prop === 'function')
  {
    const method = prop;
    const columns = Object.keys(data[0]);

    result = columns.reduce(
      (results, column) => ({
        ...results,
        [column]: pivotTable(data, column, method),
      }),
      {},
    );
  }

  if (this instanceof pivotTable)
  {
    this.result = result;
    return;
  }

   return result;
}

pivotTable.prototype =
{
  /**
   * Convert pivotTable data to collection
   * @example
   * { id: '2017-07-23', title: [ { id: 'male', title: 8 }, { id: 'female', title: 4 }, { id: 'count', title: 12 } ] }
   * // => [{ id, male, femail, count }, ... ]
   */
  toArray: function(transform)
  {
    if (!this.result)
    {
      return [];
    }

    return this.result.map(({ id, title }) =>
    {
      const record = {id};

      if (Array.isArray(title))
      {
        title.forEach(child => record[child.id] = child.title);
      }
      else
      {
        record[id] = title;
      }

      return typeof transform === 'function' ? transform(record) : record;
    });
  },
};

export default pivotTable;
<|endoftext|>


<commit_before>/**
 * Graphology Assertions
 * ======================
 *
 * Various assertions concerning graphs.
 */
var deepEqual = require('fast-deep-equal/es6');

/**
 * Helpers.
 */
function areUnorderedCollectionsOfAttributesIdentical(a1, a2) {
  var l1 = a1.length;
  var l2 = a2.length;

  if (l1 !== l2) return false;

  var o1, o2;
  var i, j;
  var matches = new Set();

  outside: for (i = 0; i < l1; i++) {
    o1 = a1[i];

    for (j = 0; j < l2; j++) {
      if (matches.has(j)) continue;

      o2 = a2[j];

      if (deepEqual(o1, o2)) {
        matches.add(j);
        continue outside;
      }
    }

    return false;
  }

  return true;
}

function compareNeighborEntries(entries1, entries2) {
  var keys1 = Object.keys(entries1);
  var keys2 = Object.keys(entries2);

  if (keys1.length !== keys2.length) return false;

  for (var k in entries1) {
    if (!areUnorderedCollectionsOfAttributesIdentical(entries1[k], entries2[k]))
      return false;
  }

  return true;
}

function countOutEdges(graph, node) {
  var counts = {};
  var c;

  graph.forEachOutEdge(node, function (_e, _ea, _s, target) {
    c = counts[target] || 0;
    c++;

    counts[target] = c;
  });

  return counts;
}

function countAssymetricUndirectedEdges(graph, node) {
  var counts = {};
  var c;

  graph.forEachUndirectedEdge(node, function (_e, _ea, source, target) {
    target = node === source ? target : source;

    if (node > target) return;

    c = counts[target] || 0;
    c++;

    counts[target] = c;
  });

  return counts;
}

function collectOutEdges(graph, node) {
  var entries = {};
  var c;

  graph.forEachOutEdge(node, function (_e, attr, _s, target) {
    c = entries[target];

    if (!c) {
      c = [];
      entries[target] = c;
    }

    c.push(attr);
  });

  return entries;
}

function collectAssymetricUndirectedEdges(graph, node) {
  var entries = {};
  var c;

  graph.forEachUndirectedEdge(node, function (_e, attr, source, target) {
    target = node === source ? target : source;

    if (node > target) return;

    c = entries[target];

    if (!c) {
      c = [];
      entries[target] = c;
    }

    c.push(attr);
  });

  return entries;
}

/**
 * Function returning whether the given graphs have the same nodes.
 *
 * @param  {boolean} deep - Whether to perform deep comparisons.
 * @param  {Graph}   G    - First graph.
 * @param  {Graph}   H    - Second graph.
 * @return {boolean}
 */
function abstractHaveSameNodes(deep, G, H) {
  if (G === H) return true;

  if (G.order !== H.order) return false;

  return G.everyNode(function (node, attr) {
    if (!H.hasNode(node)) return false;

    if (!deep) return true;

    return deepEqual(attr, H.getNodeAttributes(node));
  });
}

/**
 * Function returning whether the given graphs are identical.
 *
 * @param  {boolean} deep    - Whether to perform deep comparison.
 * @param  {boolean} relaxed - Whether to allow graph options to differ.
 * @param  {Graph}   G       - First graph.
 * @param  {Graph}   H       - Second graph.
 * @return {boolean}
 */
function abstractAreSameGraphs(deep, relaxed, G, H) {
  if (G === H) return true;

  // If two graphs have incompatible settings they cannot be identical
  if (relaxed) {
    if (
      (G.type === 'directed' && H.type === 'undirected') ||
      (G.type === 'undirected' && H.type === 'directed')
    )
      return false;
  }

  // If two graphs don't have the same settings they cannot be identical
  else {
    if (
      G.type !== H.type ||
      G.allowSelfLoops !== H.allowSelfLoops ||
      G.multi !== H.multi
    )
      return false;
  }

  // If two graphs don't have the same number of typed edges, they cannot be identical
  if (
    G.directedSize !== H.directedSize ||
    G.undirectedSize !== H.undirectedSize
  )
    return false;

  // If two graphs don't have the same nodes they cannot be identical
  if (!abstractHaveSameNodes(deep, G, H)) return false;

  var sameDirectedEdges = false;
  var sameUndirectedEdges = false;

  // In the simple case we don't need refining
  if (!G.multi && !H.multi) {
    sameDirectedEdges = G.everyDirectedEdge(function (_e, _ea, source, target) {
      if (!H.hasDirectedEdge(source, target)) return false;

      if (!deep) return true;

      return deepEqual(
        G.getDirectedEdgeAttributes(source, target),
        H.getDirectedEdgeAttributes(source, target)
      );
    });

    if (!sameDirectedEdges) return false;

    sameUndirectedEdges = G.everyUndirectedEdge(function (
      _e,
      _ea,
      source,
      target
    ) {
      if (!H.hasUndirectedEdge(source, target)) return false;

      if (!deep) return true;

      return deepEqual(
        G.getUndirectedEdgeAttributes(source, target),
        H.getUndirectedEdgeAttributes(source, target)
      );
    });

    if (!sameUndirectedEdges) return false;
  }

  // In the multi case, things are a bit more complex
  else {
    var aggregationFunction = deep ? collectOutEdges : countOutEdges;
    var comparisonFunction = deep ? compareNeighborEntries : deepEqual;

    sameDirectedEdges = G.everyNode(function (node) {
      var gCounts = aggregationFunction(G, node);
      var hCounts = aggregationFunction(H, node);

      return comparisonFunction(gCounts, hCounts);
    });

    if (!sameDirectedEdges) return false;

    aggregationFunction = deep
      ? collectAssymetricUndirectedEdges
      : countAssymetricUndirectedEdges;

    sameUndirectedEdges = G.everyNode(function (node) {
      var gCounts = aggregationFunction(G, node);
      var hCounts = aggregationFunction(H, node);

      return comparisonFunction(gCounts, hCounts);
    });

    if (!sameUndirectedEdges) return false;
  }

  return true;
}

/**
 * Exporting.
 */
exports.isGraph = require('graphology-utils/is-graph');
exports.isGraphConstructor = require('graphology-utils/is-graph-constructor');
exports.haveSameNodes = abstractHaveSameNodes.bind(null, false);
exports.haveSameNodesDeep = abstractHaveSameNodes.bind(null, true);
exports.areSameGraphs = abstractAreSameGraphs.bind(null, false, false);
exports.areSameGraphsDeep = abstractAreSameGraphs.bind(null, true, false);
exports.haveSameEdges = abstractAreSameGraphs.bind(null, false, true);
exports.haveSameEdgesDeep = abstractAreSameGraphs.bind(null, true, true);
<commit_msg>[assertions] slight optimization<commit_after>/**
 * Graphology Assertions
 * ======================
 *
 * Various assertions concerning graphs.
 */
var deepEqual = require('fast-deep-equal/es6');

/**
 * Constants.
 */
var SIZE = Symbol('size');

/**
 * Helpers.
 */
function areUnorderedCollectionsOfAttributesIdentical(a1, a2) {
  var l1 = a1.length;
  var l2 = a2.length;

  if (l1 !== l2) return false;

  var o1, o2;
  var i, j;
  var matches = new Set();

  outside: for (i = 0; i < l1; i++) {
    o1 = a1[i];

    for (j = 0; j < l2; j++) {
      if (matches.has(j)) continue;

      o2 = a2[j];

      if (deepEqual(o1, o2)) {
        matches.add(j);
        continue outside;
      }
    }

    return false;
  }

  return true;
}

function compareNeighborEntries(entries1, entries2) {
  if (entries1[SIZE] !== entries2[SIZE]) return false;

  for (var k in entries1) {
    if (!areUnorderedCollectionsOfAttributesIdentical(entries1[k], entries2[k]))
      return false;
  }

  return true;
}

function countOutEdges(graph, node) {
  var counts = {};
  var c;

  graph.forEachOutEdge(node, function (_e, _ea, _s, target) {
    c = counts[target] || 0;
    c++;

    counts[target] = c;
  });

  return counts;
}

function countAssymetricUndirectedEdges(graph, node) {
  var counts = {};
  var c;

  graph.forEachUndirectedEdge(node, function (_e, _ea, source, target) {
    target = node === source ? target : source;

    if (node > target) return;

    c = counts[target] || 0;
    c++;

    counts[target] = c;
  });

  return counts;
}

function collectOutEdges(graph, node) {
  var entries = {};
  entries[SIZE] = 0;
  var c;

  graph.forEachOutEdge(node, function (_e, attr, _s, target) {
    c = entries[target];

    if (!c) {
      c = [];
      entries[SIZE] += 1;
      entries[target] = c;
    }

    c.push(attr);
  });

  return entries;
}

function collectAssymetricUndirectedEdges(graph, node) {
  var entries = {};
  entries[SIZE] = 0;
  var c;

  graph.forEachUndirectedEdge(node, function (_e, attr, source, target) {
    target = node === source ? target : source;

    if (node > target) return;

    c = entries[target];

    if (!c) {
      c = [];
      entries[SIZE] += 1;
      entries[target] = c;
    }

    c.push(attr);
  });

  return entries;
}

/**
 * Function returning whether the given graphs have the same nodes.
 *
 * @param  {boolean} deep - Whether to perform deep comparisons.
 * @param  {Graph}   G    - First graph.
 * @param  {Graph}   H    - Second graph.
 * @return {boolean}
 */
function abstractHaveSameNodes(deep, G, H) {
  if (G === H) return true;

  if (G.order !== H.order) return false;

  return G.everyNode(function (node, attr) {
    if (!H.hasNode(node)) return false;

    if (!deep) return true;

    return deepEqual(attr, H.getNodeAttributes(node));
  });
}

/**
 * Function returning whether the given graphs are identical.
 *
 * @param  {boolean} deep    - Whether to perform deep comparison.
 * @param  {boolean} relaxed - Whether to allow graph options to differ.
 * @param  {Graph}   G       - First graph.
 * @param  {Graph}   H       - Second graph.
 * @return {boolean}
 */
function abstractAreSameGraphs(deep, relaxed, G, H) {
  if (G === H) return true;

  // If two graphs have incompatible settings they cannot be identical
  if (relaxed) {
    if (
      (G.type === 'directed' && H.type === 'undirected') ||
      (G.type === 'undirected' && H.type === 'directed')
    )
      return false;
  }

  // If two graphs don't have the same settings they cannot be identical
  else {
    if (
      G.type !== H.type ||
      G.allowSelfLoops !== H.allowSelfLoops ||
      G.multi !== H.multi
    )
      return false;
  }

  // If two graphs don't have the same number of typed edges, they cannot be identical
  if (
    G.directedSize !== H.directedSize ||
    G.undirectedSize !== H.undirectedSize
  )
    return false;

  // If two graphs don't have the same nodes they cannot be identical
  if (!abstractHaveSameNodes(deep, G, H)) return false;

  var sameDirectedEdges = false;
  var sameUndirectedEdges = false;

  // In the simple case we don't need refining
  if (!G.multi && !H.multi) {
    sameDirectedEdges = G.everyDirectedEdge(function (_e, _ea, source, target) {
      if (!H.hasDirectedEdge(source, target)) return false;

      if (!deep) return true;

      return deepEqual(
        G.getDirectedEdgeAttributes(source, target),
        H.getDirectedEdgeAttributes(source, target)
      );
    });

    if (!sameDirectedEdges) return false;

    sameUndirectedEdges = G.everyUndirectedEdge(function (
      _e,
      _ea,
      source,
      target
    ) {
      if (!H.hasUndirectedEdge(source, target)) return false;

      if (!deep) return true;

      return deepEqual(
        G.getUndirectedEdgeAttributes(source, target),
        H.getUndirectedEdgeAttributes(source, target)
      );
    });

    if (!sameUndirectedEdges) return false;
  }

  // In the multi case, things are a bit more complex
  else {
    var aggregationFunction = deep ? collectOutEdges : countOutEdges;
    var comparisonFunction = deep ? compareNeighborEntries : deepEqual;

    sameDirectedEdges = G.everyNode(function (node) {
      var gCounts = aggregationFunction(G, node);
      var hCounts = aggregationFunction(H, node);

      return comparisonFunction(gCounts, hCounts);
    });

    if (!sameDirectedEdges) return false;

    aggregationFunction = deep
      ? collectAssymetricUndirectedEdges
      : countAssymetricUndirectedEdges;

    sameUndirectedEdges = G.everyNode(function (node) {
      var gCounts = aggregationFunction(G, node);
      var hCounts = aggregationFunction(H, node);

      return comparisonFunction(gCounts, hCounts);
    });

    if (!sameUndirectedEdges) return false;
  }

  return true;
}

/**
 * Exporting.
 */
exports.isGraph = require('graphology-utils/is-graph');
exports.isGraphConstructor = require('graphology-utils/is-graph-constructor');
exports.haveSameNodes = abstractHaveSameNodes.bind(null, false);
exports.haveSameNodesDeep = abstractHaveSameNodes.bind(null, true);
exports.areSameGraphs = abstractAreSameGraphs.bind(null, false, false);
exports.areSameGraphsDeep = abstractAreSameGraphs.bind(null, true, false);
exports.haveSameEdges = abstractAreSameGraphs.bind(null, false, true);
exports.haveSameEdgesDeep = abstractAreSameGraphs.bind(null, true, true);
<|endoftext|>