<commit_before>/**
 * @ngdoc module
 * @name material.components.list
 * @description
 * List module
 */
angular.module('material.components.list', [
  'material.core'
])
  .controller('MdListController', MdListController)
  .directive('mdList', mdListDirective)
  .directive('mdListItem', mdListItemDirective);

/**
 * @ngdoc directive
 * @name mdList
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<md-list>` directive is a list container for 1..n `<md-list-item>` tags.
 *
 * @usage
 * <hljs lang="html">
 * <md-list>
 *   <md-list-item class="md-2-line" ng-repeat="item in todos">
 *     <md-checkbox ng-model="item.done"></md-checkbox>
 *

 *
{{item.title}}

 *
{{item.description}}

 *

 *   </md-list-item>
 * </md-list>
 * </hljs>
 */

function mdListDirective($mdTheming) {
  return {
    restrict: 'E',
    compile: function(tEl) {
      tEl[0].setAttribute('role', 'list');
      return $mdTheming;
    }
  };
}
/**
 * @ngdoc directive
 * @name mdListItem
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<md-list-item>` directive is a container intended for row items in a `<md-list>` container.
 * The `md-2-line` and `md-3-line` classes can be added to a `<md-list-item>`
 * to increase the height with 22px and 40px respectively.
 *
 * ## CSS
 * `.md-avatar` - class for image avatars
 *
 * `.md-avatar-icon` - class for icon avatars
 *
 * `.md-offset` - on content without an avatar
 *
 * @usage
 * <hljs lang="html">
 *  <md-list>
 *    <md-list-item>
 *
 *      Item content in list
 *    </md-list-item>
 *    <md-list-item>
 *      <md-icon class="md-avatar-icon" md-svg-icon="communication:phone"></md-icon>
 *      Item content in list
 *    </md-list-item>
 *  </md-list>
 * </hljs>
 *
 * _**Note:** We automatically apply special styling when the inner contents are wrapped inside
 * of a `<md-button>` tag. This styling is automatically ignored for `class="md-secondary"` buttons
 * and you can include a class of `class="md-exclude"` if you need to use a non-secondary button
 * that is inside the list, but does not wrap the contents._
 */
function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
  var proxiedTypes = ['md-checkbox', 'md-switch'];
  return {
    restrict: 'E',
    controller: 'MdListController',
    compile: function(tEl, tAttrs) {
      // Check for proxy controls (no ng-click on parent, and a control inside)
      var secondaryItems = tEl[0].querySelectorAll('.md-secondary');
      var hasProxiedElement;
      var proxyElement;

      tEl[0].setAttribute('role', 'listitem');

      if (tAttrs.ngClick || tAttrs.ngHref || tAttrs.href || tAttrs.uiSref || tAttrs.ngAttrUiSref) {
        wrapIn('button');
      } else {
        for (var i = 0, type; type = proxiedTypes[i]; ++i) {
          if (proxyElement = tEl[0].querySelector(type)) {
            hasProxiedElement = true;
            break;
          }
        }
        if (hasProxiedElement) {
          wrapIn('div');
        } else if (!tEl[0].querySelector('md-button:not(.md-secondary):not(.md-exclude)')) {
          tEl.addClass('_md-no-proxy');
        }
      }
      wrapSecondaryItems();
      setupToggleAria();

      function setupToggleAria() {
        var toggleTypes = ['md-switch', 'md-checkbox'];
        var toggle;

        for (var i = 0, toggleType; toggleType = toggleTypes[i]; ++i) {
          if (toggle = tEl.find(toggleType)[0]) {
            if (!toggle.hasAttribute('aria-label')) {
              var p = tEl.find('p')[0];
              if (!p) return;
              toggle.setAttribute('aria-label', 'Toggle ' + p.textContent);
            }
          }
        }
      }

      function wrapIn(type) {
        var container;
        if (type == 'div') {
          container = angular.element('
');
          container.append(tEl.contents());
          tEl.addClass('_md-proxy-focus');
        } else {
          // Element which holds the default list-item content.
          container = angular.element(
            '
'+
            '

'+
            '
'
          );

          // Button which shows ripple and executes primary action.
          var buttonWrap = angular.element(
            '<md-button class="_md-no-style" md-no-focus-style></md-button>'
          );

          buttonWrap[0].setAttribute('aria-label', tEl[0].textContent);
          copyAttributes(tEl[0], buttonWrap[0]);

          // Append the button wrap before our list-item content, because it will overlay in relative.
          container.prepend(buttonWrap);
          container.children().eq(1).append(tEl.contents());

          tEl.addClass('_md-button-wrap');
        }

        tEl[0].setAttribute('tabindex', '-1');
        tEl.append(container);
      }

      function wrapSecondaryItems() {
        if (secondaryItems.length === 1) {
          wrapSecondaryItem(secondaryItems[0], tEl);
        } else if (secondaryItems.length > 1) {
          var secondaryItemsWrapper = angular.element('
');
          angular.forEach(secondaryItems, function(secondaryItem) {
            wrapSecondaryItem(secondaryItem, secondaryItemsWrapper, true);
          });
          tEl.append(secondaryItemsWrapper);
        }
      }

      function wrapSecondaryItem(secondaryItem, container, hasSecondaryItemsWrapper) {
        if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) {
          $mdAria.expect(secondaryItem, 'aria-label');
          var buttonWrapper;
          if (hasSecondaryItemsWrapper) {
            buttonWrapper = angular.element('<md-button class="md-icon-button">');
          } else {
            buttonWrapper = angular.element('<md-button class="_md-secondary-container md-icon-button">');
          }
          copyAttributes(secondaryItem, buttonWrapper[0]);
          secondaryItem.setAttribute('tabindex', '-1');
          secondaryItem.classList.remove('md-secondary');
          buttonWrapper.append(secondaryItem);
          secondaryItem = buttonWrapper[0];
        }

        // Check for a secondary item and move it outside
        if ( secondaryItem && (
                secondaryItem.hasAttribute('ng-click') ||
                ( tAttrs.ngClick &&
                isProxiedElement(secondaryItem) )
            )) {
          // When using multiple secondary items we need to remove their secondary class to be
          // orderd correctly in the list-item
          if (hasSecondaryItemsWrapper) {
            secondaryItem.classList.remove('md-secondary');
          }
          tEl.addClass('md-with-secondary');
          container.append(secondaryItem);
        }
      }

      function copyAttributes(item, wrapper) {
        var copiedAttrs = ['ng-if', 'ng-click', 'aria-label', 'ng-disabled',
          'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref'];
        angular.forEach(copiedAttrs, function(attr) {
          if (item.hasAttribute(attr)) {
            wrapper.setAttribute(attr, item.getAttribute(attr));
            item.removeAttribute(attr);
          }
        });
      }

      function isProxiedElement(el) {
        return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
      }

      function isButton(el) {
        var nodeName = el.nodeName.toUpperCase();

        return nodeName == "MD-BUTTON" || nodeName == "BUTTON";
      }

      return postLink;

      function postLink($scope, $element, $attr, ctrl) {

        var proxies    = [],
            firstChild = $element[0].firstElementChild,
            hasClick   = firstChild && firstChild.firstElementChild &&
                         hasClickEvent(firstChild.firstElementChild);

        computeProxies();
        computeClickable();

        if ($element.hasClass('_md-proxy-focus') && proxies.length) {
          angular.forEach(proxies, function(proxy) {
            proxy = angular.element(proxy);

            $scope.mouseActive = false;
            proxy.on('mousedown', function() {
              $scope.mouseActive = true;
              $timeout(function(){
                $scope.mouseActive = false;
              }, 100);
            })
            .on('focus', function() {
              if ($scope.mouseActive === false) { $element.addClass('md-focused'); }
              proxy.on('blur', function proxyOnBlur() {
                $element.removeClass('md-focused');
                proxy.off('blur', proxyOnBlur);
              });
            });
          });
        }

        function hasClickEvent (element) {
          var attr = element.attributes;
          for (var i = 0; i < attr.length; i++) {
            if ($attr.$normalize(attr[i].name) === 'ngClick') return true;
          }
          return false;
        }

        function computeProxies() {
          var children = $element.children();
          if (children.length && !children[0].hasAttribute('ng-click')) {
            angular.forEach(proxiedTypes, function(type) {
              angular.forEach(firstChild.querySelectorAll(type), function(child) {
                proxies.push(child);
              });
            });
          }
        }
        function computeClickable() {
          if (proxies.length == 1 || hasClick) {
            $element.addClass('md-clickable');

            if (!hasClick) {
              ctrl.attachRipple($scope, angular.element($element[0].querySelector('._md-no-style')));
            }
          }
        }

        var firstChildKeypressListener = function(e) {
          if (e.target.nodeName != 'INPUT' && e.target.nodeName != 'TEXTAREA' && !e.target.isContentEditable) {
            var keyCode = e.which || e.keyCode;
            if (keyCode == $mdConstant.KEY_CODE.SPACE) {
              if (firstChild) {
                firstChild.click();
                e.preventDefault();
                e.stopPropagation();
              }
            }
          }
        };

        if (!hasClick && !proxies.length) {
          firstChild && firstChild.addEventListener('keypress', firstChildKeypressListener);
        }

        $element.off('click');
        $element.off('keypress');

        if (proxies.length == 1 && firstChild) {
          $element.children().eq(0).on('click', function(e) {
            var parentButton = $mdUtil.getClosest(e.target, 'BUTTON');
            if (!parentButton && firstChild.contains(e.target)) {
              angular.forEach(proxies, function(proxy) {
                if (e.target !== proxy && !proxy.contains(e.target)) {
                  angular.element(proxy).triggerHandler('click');
                }
              });
            }
          });
        }

        $scope.$on('$destroy', function () {
          firstChild && firstChild.removeEventListener('keypress', firstChildKeypressListener);
        });
      }
    }
  };
}

/*
 * @private
 * @ngdoc controller
 * @name MdListController
 * @module material.components.list
 *
 */
function MdListController($scope, $element, $mdListInkRipple) {
  var ctrl = this;
  ctrl.attachRipple = attachRipple;

  function attachRipple (scope, element) {
    var options = {};
    $mdListInkRipple.attach(scope, element, options);
  }
}

<commit_msg>feat(list): add ui-sref-opts attribute to button executor.<commit_after>/**
 * @ngdoc module
 * @name material.components.list
 * @description
 * List module
 */
angular.module('material.components.list', [
  'material.core'
])
  .controller('MdListController', MdListController)
  .directive('mdList', mdListDirective)
  .directive('mdListItem', mdListItemDirective);

/**
 * @ngdoc directive
 * @name mdList
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<md-list>` directive is a list container for 1..n `<md-list-item>` tags.
 *
 * @usage
 * <hljs lang="html">
 * <md-list>
 *   <md-list-item class="md-2-line" ng-repeat="item in todos">
 *     <md-checkbox ng-model="item.done"></md-checkbox>
 *

 *
{{item.title}}

 *
{{item.description}}

 *

 *   </md-list-item>
 * </md-list>
 * </hljs>
 */

function mdListDirective($mdTheming) {
  return {
    restrict: 'E',
    compile: function(tEl) {
      tEl[0].setAttribute('role', 'list');
      return $mdTheming;
    }
  };
}
/**
 * @ngdoc directive
 * @name mdListItem
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<md-list-item>` directive is a container intended for row items in a `<md-list>` container.
 * The `md-2-line` and `md-3-line` classes can be added to a `<md-list-item>`
 * to increase the height with 22px and 40px respectively.
 *
 * ## CSS
 * `.md-avatar` - class for image avatars
 *
 * `.md-avatar-icon` - class for icon avatars
 *
 * `.md-offset` - on content without an avatar
 *
 * @usage
 * <hljs lang="html">
 *  <md-list>
 *    <md-list-item>
 *
 *      Item content in list
 *    </md-list-item>
 *    <md-list-item>
 *      <md-icon class="md-avatar-icon" md-svg-icon="communication:phone"></md-icon>
 *      Item content in list
 *    </md-list-item>
 *  </md-list>
 * </hljs>
 *
 * _**Note:** We automatically apply special styling when the inner contents are wrapped inside
 * of a `<md-button>` tag. This styling is automatically ignored for `class="md-secondary"` buttons
 * and you can include a class of `class="md-exclude"` if you need to use a non-secondary button
 * that is inside the list, but does not wrap the contents._
 */
function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
  var proxiedTypes = ['md-checkbox', 'md-switch'];
  return {
    restrict: 'E',
    controller: 'MdListController',
    compile: function(tEl, tAttrs) {
      // Check for proxy controls (no ng-click on parent, and a control inside)
      var secondaryItems = tEl[0].querySelectorAll('.md-secondary');
      var hasProxiedElement;
      var proxyElement;

      tEl[0].setAttribute('role', 'listitem');

      if (tAttrs.ngClick || tAttrs.ngHref || tAttrs.href || tAttrs.uiSref || tAttrs.ngAttrUiSref) {
        wrapIn('button');
      } else {
        for (var i = 0, type; type = proxiedTypes[i]; ++i) {
          if (proxyElement = tEl[0].querySelector(type)) {
            hasProxiedElement = true;
            break;
          }
        }
        if (hasProxiedElement) {
          wrapIn('div');
        } else if (!tEl[0].querySelector('md-button:not(.md-secondary):not(.md-exclude)')) {
          tEl.addClass('_md-no-proxy');
        }
      }
      wrapSecondaryItems();
      setupToggleAria();

      function setupToggleAria() {
        var toggleTypes = ['md-switch', 'md-checkbox'];
        var toggle;

        for (var i = 0, toggleType; toggleType = toggleTypes[i]; ++i) {
          if (toggle = tEl.find(toggleType)[0]) {
            if (!toggle.hasAttribute('aria-label')) {
              var p = tEl.find('p')[0];
              if (!p) return;
              toggle.setAttribute('aria-label', 'Toggle ' + p.textContent);
            }
          }
        }
      }

      function wrapIn(type) {
        var container;
        if (type == 'div') {
          container = angular.element('
');
          container.append(tEl.contents());
          tEl.addClass('_md-proxy-focus');
        } else {
          // Element which holds the default list-item content.
          container = angular.element(
            '
'+
            '

'+
            '
'
          );

          // Button which shows ripple and executes primary action.
          var buttonWrap = angular.element(
            '<md-button class="_md-no-style" md-no-focus-style></md-button>'
          );

          buttonWrap[0].setAttribute('aria-label', tEl[0].textContent);
          copyAttributes(tEl[0], buttonWrap[0]);

          // Append the button wrap before our list-item content, because it will overlay in relative.
          container.prepend(buttonWrap);
          container.children().eq(1).append(tEl.contents());

          tEl.addClass('_md-button-wrap');
        }

        tEl[0].setAttribute('tabindex', '-1');
        tEl.append(container);
      }

      function wrapSecondaryItems() {
        if (secondaryItems.length === 1) {
          wrapSecondaryItem(secondaryItems[0], tEl);
        } else if (secondaryItems.length > 1) {
          var secondaryItemsWrapper = angular.element('
');
          angular.forEach(secondaryItems, function(secondaryItem) {
            wrapSecondaryItem(secondaryItem, secondaryItemsWrapper, true);
          });
          tEl.append(secondaryItemsWrapper);
        }
      }

      function wrapSecondaryItem(secondaryItem, container, hasSecondaryItemsWrapper) {
        if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) {
          $mdAria.expect(secondaryItem, 'aria-label');
          var buttonWrapper;
          if (hasSecondaryItemsWrapper) {
            buttonWrapper = angular.element('<md-button class="md-icon-button">');
          } else {
            buttonWrapper = angular.element('<md-button class="_md-secondary-container md-icon-button">');
          }
          copyAttributes(secondaryItem, buttonWrapper[0]);
          secondaryItem.setAttribute('tabindex', '-1');
          secondaryItem.classList.remove('md-secondary');
          buttonWrapper.append(secondaryItem);
          secondaryItem = buttonWrapper[0];
        }

        // Check for a secondary item and move it outside
        if ( secondaryItem && (
                secondaryItem.hasAttribute('ng-click') ||
                ( tAttrs.ngClick &&
                isProxiedElement(secondaryItem) )
            )) {
          // When using multiple secondary items we need to remove their secondary class to be
          // orderd correctly in the list-item
          if (hasSecondaryItemsWrapper) {
            secondaryItem.classList.remove('md-secondary');
          }
          tEl.addClass('md-with-secondary');
          container.append(secondaryItem);
        }
      }

      function copyAttributes(item, wrapper) {
        var copiedAttrs = ['ng-if', 'ng-click', 'aria-label', 'ng-disabled',
          'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref', 'ui-sref-opts'];

        angular.forEach(copiedAttrs, function(attr) {
          if (item.hasAttribute(attr)) {
            wrapper.setAttribute(attr, item.getAttribute(attr));
            item.removeAttribute(attr);
          }
        });
      }

      function isProxiedElement(el) {
        return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
      }

      function isButton(el) {
        var nodeName = el.nodeName.toUpperCase();

        return nodeName == "MD-BUTTON" || nodeName == "BUTTON";
      }

      return postLink;

      function postLink($scope, $element, $attr, ctrl) {

        var proxies    = [],
            firstChild = $element[0].firstElementChild,
            hasClick   = firstChild && firstChild.firstElementChild &&
                         hasClickEvent(firstChild.firstElementChild);

        computeProxies();
        computeClickable();

        if ($element.hasClass('_md-proxy-focus') && proxies.length) {
          angular.forEach(proxies, function(proxy) {
            proxy = angular.element(proxy);

            $scope.mouseActive = false;
            proxy.on('mousedown', function() {
              $scope.mouseActive = true;
              $timeout(function(){
                $scope.mouseActive = false;
              }, 100);
            })
            .on('focus', function() {
              if ($scope.mouseActive === false) { $element.addClass('md-focused'); }
              proxy.on('blur', function proxyOnBlur() {
                $element.removeClass('md-focused');
                proxy.off('blur', proxyOnBlur);
              });
            });
          });
        }

        function hasClickEvent (element) {
          var attr = element.attributes;
          for (var i = 0; i < attr.length; i++) {
            if ($attr.$normalize(attr[i].name) === 'ngClick') return true;
          }
          return false;
        }

        function computeProxies() {
          var children = $element.children();
          if (children.length && !children[0].hasAttribute('ng-click')) {
            angular.forEach(proxiedTypes, function(type) {
              angular.forEach(firstChild.querySelectorAll(type), function(child) {
                proxies.push(child);
              });
            });
          }
        }
        function computeClickable() {
          if (proxies.length == 1 || hasClick) {
            $element.addClass('md-clickable');

            if (!hasClick) {
              ctrl.attachRipple($scope, angular.element($element[0].querySelector('._md-no-style')));
            }
          }
        }

        var firstChildKeypressListener = function(e) {
          if (e.target.nodeName != 'INPUT' && e.target.nodeName != 'TEXTAREA' && !e.target.isContentEditable) {
            var keyCode = e.which || e.keyCode;
            if (keyCode == $mdConstant.KEY_CODE.SPACE) {
              if (firstChild) {
                firstChild.click();
                e.preventDefault();
                e.stopPropagation();
              }
            }
          }
        };

        if (!hasClick && !proxies.length) {
          firstChild && firstChild.addEventListener('keypress', firstChildKeypressListener);
        }

        $element.off('click');
        $element.off('keypress');

        if (proxies.length == 1 && firstChild) {
          $element.children().eq(0).on('click', function(e) {
            var parentButton = $mdUtil.getClosest(e.target, 'BUTTON');
            if (!parentButton && firstChild.contains(e.target)) {
              angular.forEach(proxies, function(proxy) {
                if (e.target !== proxy && !proxy.contains(e.target)) {
                  angular.element(proxy).triggerHandler('click');
                }
              });
            }
          });
        }

        $scope.$on('$destroy', function () {
          firstChild && firstChild.removeEventListener('keypress', firstChildKeypressListener);
        });
      }
    }
  };
}

/*
 * @private
 * @ngdoc controller
 * @name MdListController
 * @module material.components.list
 *
 */
function MdListController($scope, $element, $mdListInkRipple) {
  var ctrl = this;
  ctrl.attachRipple = attachRipple;

  function attachRipple (scope, element) {
    var options = {};
    $mdListInkRipple.attach(scope, element, options);
  }
}

<|endoftext|>


<commit_before>/* global module, inject, chai, Datamap, STATES_TOPOJSON, DISTRICT_TOPOJSON, BLOCK_TOPOJSON */
"use strict";

var utils = hqImport('icds_reports/js/spec/utils');
var pageData = hqImport('hqwebapp/js/initial_page_data');

describe('Indie Map Directive', function () {

    var $scope, $location, controller, $httpBackend, $storageService;

    pageData.registerUrl('icds_locations', 'icds_locations');

    var mockGeography = {
        geometry: {type: "Polygon", coordinates: []},
        id: "test-id",
        properties: {STATE_CODE: "09", name: "Uttar Pradesh"},
        type: "Feature",
    };

    var mockData = {
        data: {'test-id': {in_month: 0, original_name: ['Uttar Pradesh'], birth: 0, fillKey: "0%-20%"}},
    };

    var mockFakeData = {
        data: {'test-id': {in_month: 0, original_name: [], birth: 0, fillKey: "0%-20%"}},
    };

    var mockLocation = {
        location_type_name: "state",
        parent_id: null,
        location_id: "9951736acfe54c68948225cc05fbbd63",
        name: "Chhattisgarh",
    };

    var mockLocations = {
        'locations': [{
            location_type_name: "state",
            parent_id: null,
            location_id: "9951736acfe54c68948225cc05fbbd63",
            name: "Chhattisgarh",
        }],
    };

    beforeEach(module('icdsApp', function ($provide) {
        utils.provideDefaultConstants($provide, false, false);
        $provide.constant('haveAccessToFeatures', false);

    }));

    beforeEach(inject(function ($rootScope, _$compile_, _$location_, _$httpBackend_, storageService) {
        $scope = $rootScope.$new();
        $location = _$location_;
        $httpBackend = _$httpBackend_;
        $storageService = storageService;

        $httpBackend.expectGET('icds_locations').respond(200, mockLocation);

        var element = window.angular.element("<indie-map data='test'></indie-map>");
        var compiled = _$compile_(element)($scope);

        $httpBackend.flush();
        $scope.$digest();

        controller = compiled.controller('indieMap');
    }));

    it('tests instantiate the controller properly', function () {
        chai.expect(controller).not.to.be.a('undefined');
    });

    it('tests init topo json when location level not exist', function () {
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, null);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal -1', function () {
        $location.search('selectedLocationLevel', -1);
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, -1);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal 4', function () {
        $location.search('selectedLocationLevel', 4);
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, 4);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal 0', function () {
        $location.search('selectedLocationLevel', 0);
        $location.search('location_name', 'Madhya Pradesh');

        var locationLevel = $location.search()['selectedLocationLevel'];
        var location = {
            location_type: "state",
            location_type_name: "state",
            map_location_name: "Madhya Pradesh",
            name: "Madhya Pradesh",
        };

        assert.equal(locationLevel, 0);
        assert.equal(location.name, 'Madhya Pradesh');

        controller.initTopoJson(locationLevel, location);

        assert.equal(controller.scope, 'Madhya Pradesh');
        assert.equal(controller.type, 'Madhya PradeshTopo');
        assert.equal(Datamap.prototype['Madhya PradeshTopo'], DISTRICT_TOPOJSON);
    });

    it('tests init topo json when location level equal 1', function () {
        $location.search('selectedLocationLevel', 1);
        $location.search('location_name', 'Anantapur');

        var locationLevel = $location.search()['selectedLocationLevel'];
        var location = {
            location_type: "district",
            location_type_name: "district",
            map_location_name: "Anantapur",
            name: "Anantapur",
        };

        assert.equal(locationLevel, 1);
        assert.equal(location.name, 'Anantapur');

        controller.initTopoJson(locationLevel, location);

        assert.equal(controller.scope, 'Anantapur');
        assert.equal(controller.type, 'AnantapurTopo');
        assert.equal(Datamap.prototype['AnantapurTopo'], BLOCK_TOPOJSON);
    });

    it('tests html content of update map', function () {
        controller.data = mockData;
        var expected = '
<button type="button" class="close" ' +
            'ng-click="$ctrl.closePopup()" aria-label="Close">×' +
            '</button>

<button class="btn btn-xs btn-default" ' +
            'ng-click="$ctrl.updateMap(\'Uttar Pradesh\')">Uttar Pradesh</button>
';

        var result = controller.getHtmlContent(mockGeography);
        assert.equal(expected, result);
    });

    it('tests update map', function () {
        controller.data = mockFakeData;

        var expected = {};
        var result = $location.search();

        assert.deepEqual(expected, result);
        assert.deepEqual($storageService.getKey('search'), {
            "location_id": null,
        });

        $httpBackend.expectGET('icds_locations?name=test-id').respond(200, mockLocations);
        controller.updateMap(mockGeography);
        $httpBackend.flush();

        expected = {"location_id": "9951736acfe54c68948225cc05fbbd63", "location_name": "test-id"};
        result = $location.search();

        assert.deepEqual(expected, result);
        assert.deepEqual($storageService.getKey('search'), {
            "location_name": "test-id", "location_id": "9951736acfe54c68948225cc05fbbd63",
        });
    });
});
<commit_msg>bump test timeout due to increased topojson size<commit_after>/* global module, inject, chai, Datamap, STATES_TOPOJSON, DISTRICT_TOPOJSON, BLOCK_TOPOJSON */
"use strict";

var utils = hqImport('icds_reports/js/spec/utils');
var pageData = hqImport('hqwebapp/js/initial_page_data');

describe('Indie Map Directive', function () {
    this.timeout(10000);  // bump timeout for maps tests because they are slow...

    var $scope, $location, controller, $httpBackend, $storageService;

    pageData.registerUrl('icds_locations', 'icds_locations');

    var mockGeography = {
        geometry: {type: "Polygon", coordinates: []},
        id: "test-id",
        properties: {STATE_CODE: "09", name: "Uttar Pradesh"},
        type: "Feature",
    };

    var mockData = {
        data: {'test-id': {in_month: 0, original_name: ['Uttar Pradesh'], birth: 0, fillKey: "0%-20%"}},
    };

    var mockFakeData = {
        data: {'test-id': {in_month: 0, original_name: [], birth: 0, fillKey: "0%-20%"}},
    };

    var mockLocation = {
        location_type_name: "state",
        parent_id: null,
        location_id: "9951736acfe54c68948225cc05fbbd63",
        name: "Chhattisgarh",
    };

    var mockLocations = {
        'locations': [{
            location_type_name: "state",
            parent_id: null,
            location_id: "9951736acfe54c68948225cc05fbbd63",
            name: "Chhattisgarh",
        }],
    };

    beforeEach(module('icdsApp', function ($provide) {
        utils.provideDefaultConstants($provide, false, false);
        $provide.constant('haveAccessToFeatures', false);

    }));

    beforeEach(inject(function ($rootScope, _$compile_, _$location_, _$httpBackend_, storageService) {
        $scope = $rootScope.$new();
        $location = _$location_;
        $httpBackend = _$httpBackend_;
        $storageService = storageService;

        $httpBackend.expectGET('icds_locations').respond(200, mockLocation);

        var element = window.angular.element("<indie-map data='test'></indie-map>");
        var compiled = _$compile_(element)($scope);

        $httpBackend.flush();
        $scope.$digest();

        controller = compiled.controller('indieMap');
    }));

    it('tests instantiate the controller properly', function () {
        chai.expect(controller).not.to.be.a('undefined');
    });

    it('tests init topo json when location level not exist', function () {
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, null);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal -1', function () {
        $location.search('selectedLocationLevel', -1);
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, -1);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal 4', function () {
        $location.search('selectedLocationLevel', 4);
        var locationLevel = $location.search()['selectedLocationLevel'];
        assert.equal(locationLevel, 4);

        assert.equal(controller.scope, 'ind');
        assert.equal(controller.type, 'indTopo');
        assert.equal(Datamap.prototype['indTopo'], STATES_TOPOJSON);
    });

    it('tests init topo json when location level equal 0', function () {
        $location.search('selectedLocationLevel', 0);
        $location.search('location_name', 'Madhya Pradesh');

        var locationLevel = $location.search()['selectedLocationLevel'];
        var location = {
            location_type: "state",
            location_type_name: "state",
            map_location_name: "Madhya Pradesh",
            name: "Madhya Pradesh",
        };

        assert.equal(locationLevel, 0);
        assert.equal(location.name, 'Madhya Pradesh');

        controller.initTopoJson(locationLevel, location);

        assert.equal(controller.scope, 'Madhya Pradesh');
        assert.equal(controller.type, 'Madhya PradeshTopo');
        assert.equal(Datamap.prototype['Madhya PradeshTopo'], DISTRICT_TOPOJSON);
    });

    it('tests init topo json when location level equal 1', function () {
        $location.search('selectedLocationLevel', 1);
        $location.search('location_name', 'Anantapur');

        var locationLevel = $location.search()['selectedLocationLevel'];
        var location = {
            location_type: "district",
            location_type_name: "district",
            map_location_name: "Anantapur",
            name: "Anantapur",
        };

        assert.equal(locationLevel, 1);
        assert.equal(location.name, 'Anantapur');

        controller.initTopoJson(locationLevel, location);

        assert.equal(controller.scope, 'Anantapur');
        assert.equal(controller.type, 'AnantapurTopo');
        assert.equal(Datamap.prototype['AnantapurTopo'], BLOCK_TOPOJSON);
    });

    it('tests html content of update map', function () {
        controller.data = mockData;
        var expected = '
<button type="button" class="close" ' +
            'ng-click="$ctrl.closePopup()" aria-label="Close">×' +
            '</button>

<button class="btn btn-xs btn-default" ' +
            'ng-click="$ctrl.updateMap(\'Uttar Pradesh\')">Uttar Pradesh</button>
';

        var result = controller.getHtmlContent(mockGeography);
        assert.equal(expected, result);
    });

    it('tests update map', function () {
        controller.data = mockFakeData;

        var expected = {};
        var result = $location.search();

        assert.deepEqual(expected, result);
        assert.deepEqual($storageService.getKey('search'), {
            "location_id": null,
        });

        $httpBackend.expectGET('icds_locations?name=test-id').respond(200, mockLocations);
        controller.updateMap(mockGeography);
        $httpBackend.flush();

        expected = {"location_id": "9951736acfe54c68948225cc05fbbd63", "location_name": "test-id"};
        result = $location.search();

        assert.deepEqual(expected, result);
        assert.deepEqual($storageService.getKey('search'), {
            "location_name": "test-id", "location_id": "9951736acfe54c68948225cc05fbbd63",
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Analytics Settings View component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { __, _x } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME } from '../datastore/constants';
import { STORE_NAME as CORE_SITE } from '../../../googlesitekit/datastore/site/constants';
import { trackingExclusionLabels } from '../common/tracking-exclusion-switches';
import { ExistingTagError, ExistingTagNotice, ErrorNotice } from '../common';
const { useSelect } = Data;

export default function SettingsView() {
	const accountID = useSelect( ( select ) => select( STORE_NAME ).getAccountID() );
	const propertyID = useSelect( ( select ) => select( STORE_NAME ).getPropertyID() );
	const profileID = useSelect( ( select ) => select( STORE_NAME ).getProfileID() );
	const useSnippet = useSelect( ( select ) => select( STORE_NAME ).getUseSnippet() );
	const anonymizeIP = useSelect( ( select ) => select( STORE_NAME ).getAnonymizeIP() );
	const trackingDisabled = useSelect( ( select ) => select( STORE_NAME ).getTrackingDisabled() ) || [];
	const hasExistingTag = useSelect( ( select ) => select( STORE_NAME ).hasExistingTag() );
	const hasExistingTagPermission = useSelect( ( select ) => select( STORE_NAME ).hasExistingTagPermission() );
	const ampMode = useSelect( ( select ) => select( CORE_SITE ).getAMPMode() );

	return (

			{ /* Prevent showing ExistingTagError and general ErrorNotice at the same time. */ }
			{ ( ! hasExistingTag || hasExistingTagPermission ) && <ErrorNotice /> }
			{ ( hasExistingTag && ! hasExistingTagPermission && hasExistingTagPermission !== undefined ) && <ExistingTagError /> }
			{ ( hasExistingTag && hasExistingTagPermission && hasExistingTagPermission !== undefined ) && <ExistingTagNotice /> }

						{ __( 'Account', 'google-site-kit' ) }

						{ accountID || null }

						{ __( 'Property', 'google-site-kit' ) }

						{ propertyID || null }

						{ __( 'View', 'google-site-kit' ) }

						{ profileID || null }

						{ __( 'Analytics Code Snippet', 'google-site-kit' ) }

						{ useSnippet && __( 'Snippet is inserted', 'google-site-kit' ) }
						{ ! useSnippet && __( 'Snippet is not inserted', 'google-site-kit' ) }

			{ ( useSnippet && ampMode !== 'primary' ) && (

							{ __( 'IP Address Anonymization', 'google-site-kit' ) }

							{ anonymizeIP && __( 'IP addresses are being anonymized', 'google-site-kit' ) }
							{ ! anonymizeIP && __( 'IP addresses are not being anonymized', 'google-site-kit' ) }

			) }

						{ __( 'Excluded from Analytics', 'google-site-kit' ) }

						{ !! trackingDisabled.length &&
										trackingDisabled
											.map( ( exclusion ) => trackingExclusionLabels[ exclusion ] )
											.join( _x( ', ', 'list separator', 'google-site-kit' ) )
						}
						{ ! trackingDisabled.length && __( 'Analytics is currently enabled for all visitors.', 'google-site-kit' ) }

	);
}
<commit_msg>Render alternate view for no useSnippet w/ tag.<commit_after>/**
 * Analytics Settings View component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { __, _x } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME } from '../datastore/constants';
import { STORE_NAME as CORE_SITE } from '../../../googlesitekit/datastore/site/constants';
import { trackingExclusionLabels } from '../common/tracking-exclusion-switches';
import { ExistingTagError, ExistingTagNotice, ErrorNotice } from '../common';
const { useSelect } = Data;

export default function SettingsView() {
	const accountID = useSelect( ( select ) => select( STORE_NAME ).getAccountID() );
	const propertyID = useSelect( ( select ) => select( STORE_NAME ).getPropertyID() );
	const profileID = useSelect( ( select ) => select( STORE_NAME ).getProfileID() );
	const useSnippet = useSelect( ( select ) => select( STORE_NAME ).getUseSnippet() );
	const anonymizeIP = useSelect( ( select ) => select( STORE_NAME ).getAnonymizeIP() );
	const trackingDisabled = useSelect( ( select ) => select( STORE_NAME ).getTrackingDisabled() ) || [];
	const hasExistingTag = useSelect( ( select ) => select( STORE_NAME ).hasExistingTag() );
	const hasExistingTagPermission = useSelect( ( select ) => select( STORE_NAME ).hasExistingTagPermission() );
	const ampMode = useSelect( ( select ) => select( CORE_SITE ).getAMPMode() );

	return (

			{ /* Prevent showing ExistingTagError and general ErrorNotice at the same time. */ }
			{ ( ! hasExistingTag || hasExistingTagPermission ) && <ErrorNotice /> }
			{ ( hasExistingTag && ! hasExistingTagPermission && hasExistingTagPermission !== undefined ) && <ExistingTagError /> }
			{ ( hasExistingTag && hasExistingTagPermission && hasExistingTagPermission !== undefined ) && <ExistingTagNotice /> }

						{ __( 'Account', 'google-site-kit' ) }

						{ accountID || null }

						{ __( 'Property', 'google-site-kit' ) }

						{ propertyID || null }

						{ __( 'View', 'google-site-kit' ) }

						{ profileID || null }

						{ __( 'Analytics Code Snippet', 'google-site-kit' ) }

						{ useSnippet && __( 'Snippet is inserted', 'google-site-kit' ) }
						{ ( ! useSnippet && ! hasExistingTag ) && __( 'Snippet is not inserted', 'google-site-kit' ) }
						{ ( ! useSnippet && hasExistingTag ) && __( 'Inserted by another plugin or theme', 'google-site-kit' ) }

			{ ( useSnippet && ampMode !== 'primary' ) && (

							{ __( 'IP Address Anonymization', 'google-site-kit' ) }

							{ anonymizeIP && __( 'IP addresses are being anonymized', 'google-site-kit' ) }
							{ ! anonymizeIP && __( 'IP addresses are not being anonymized', 'google-site-kit' ) }

			) }

						{ __( 'Excluded from Analytics', 'google-site-kit' ) }

						{ !! trackingDisabled.length &&
										trackingDisabled
											.map( ( exclusion ) => trackingExclusionLabels[ exclusion ] )
											.join( _x( ', ', 'list separator', 'google-site-kit' ) )
						}
						{ ! trackingDisabled.length && __( 'Analytics is currently enabled for all visitors.', 'google-site-kit' ) }

	);
}
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2016
 */

/**
 * Sorts data by property.
 *
 * @param  {Realm.results}  data          The data to sort.
 * @param  {string}         sortBy        The property of the data to sort by.
 * @param  {string}         sortDataType  The type of the property, either:
 *
 *                                        'string' for alphabetical sorting (ASCII order for nums),
 *                                        'number' for numeric sorting (letters will error),
 *                                        'realm'  for default |realm.results.sorted()| sorting,
 *                                                 this is also the default sort (will error on
 *                                                 property of a property).
 *
 * @param   {boolean}        isAscending  If false, the sort order will be reversed.
 * @return  {object}                      The final sorted data.
 */
export const sortDataBy = (data, sortBy, sortDataType, isAscending = true) => {
  let sortedData;
  switch (sortDataType) {
    case 'string':
      sortedData = data.slice().sort((a, b) => a[sortBy].localeCompare(b[sortBy]));
      if (!isAscending) sortedData.reverse();
      break;
    case 'number':
      // Casts to number to cover cases where the property is a string (e.g. |serialNumber|).
      sortedData = data.slice().sort((a, b) => Number(a[sortBy]) - Number(b[sortBy]));
      if (!isAscending) sortedData.reverse();
      break;
    case 'realm':
    default:
      sortedData = data.sorted(sortBy, !isAscending);
  }
  return sortedData;
};

/**
 * Sorts an array of objects, returning a new array.
 * Sorts strings, numbers, dates or booleans.
 * @param  {Array}   data          Array of objects to sort
 * @param  {String}  sortBy        Key for the field to sort by
 * @param  {Boolean} isAscending   True if ascending, false otherwise.
 * @return {Array}   A new array of sorted data
 */
export const newSortDataBy = (data, sortBy, isAscending = true, sortDataType) => {
  const sortType =
    sortDataType ||
    {
      otherPartyName: 'string',
      itemCode: 'string',
      itemName: 'string',
      status: 'string',
      serialNumber: 'number',
      availableQuantity: 'number',
      totalQuantity: 'number',
    }[sortBy];

  switch (sortType) {
    case 'string':
      if (isAscending) return [...data.sort((a, b) => a[sortBy].localeCompare(b[sortBy]))];
      return [...data.sort((a, b) => b[sortBy].localeCompare(a[sortBy]))];
    case 'number':
      // Casts to number to cover cases where the property is a string (e.g. |serialNumber|).
      if (isAscending) return [...data.sort((a, b) => Number(a[sortBy]) - Number(b[sortBy]))];
      return [...data.sort((a, b) => Number(b[sortBy]) - Number(a[sortBy]))];
    case 'date':
      if (isAscending) return [...data.sort((a, b) => new Date(b[sortBy]) - new Date(a[sortBy]))];
      return [...data.sort((a, b) => new Date(a[sortBy]) - new Date(b[sortBy]))];
    case 'boolean':
      if (isAscending) return [...data.sort((a, b) => b[sortBy] - a[sortBy])];
      return [...data.sort((a, b) => a[sortBy] - b[sortBy])];
    default:
      throw new Error(`sortType for the field '${sortBy}' not defined`);
  }
};

export default sortDataBy;
<commit_msg>move sortKey:sortType map to module scope<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2016
 */

/**
 * Sorts data by property.
 *
 * @param  {Realm.results}  data          The data to sort.
 * @param  {string}         sortBy        The property of the data to sort by.
 * @param  {string}         sortDataType  The type of the property, either:
 *
 *                                        'string' for alphabetical sorting (ASCII order for nums),
 *                                        'number' for numeric sorting (letters will error),
 *                                        'realm'  for default |realm.results.sorted()| sorting,
 *                                                 this is also the default sort (will error on
 *                                                 property of a property).
 *
 * @param   {boolean}        isAscending  If false, the sort order will be reversed.
 * @return  {object}                      The final sorted data.
 */
export const sortDataBy = (data, sortBy, sortDataType, isAscending = true) => {
  let sortedData;
  switch (sortDataType) {
    case 'string':
      sortedData = data.slice().sort((a, b) => a[sortBy].localeCompare(b[sortBy]));
      if (!isAscending) sortedData.reverse();
      break;
    case 'number':
      // Casts to number to cover cases where the property is a string (e.g. |serialNumber|).
      sortedData = data.slice().sort((a, b) => Number(a[sortBy]) - Number(b[sortBy]));
      if (!isAscending) sortedData.reverse();
      break;
    case 'realm':
    default:
      sortedData = data.sorted(sortBy, !isAscending);
  }
  return sortedData;
};

const sortKeyToType = {
  otherPartyName: 'string',
  itemCode: 'string',
  itemName: 'string',
  status: 'string',
  serialNumber: 'number',
  availableQuantity: 'number',
  totalQuantity: 'number',
};

/**
 * Sorts an array of objects, returning a new array.
 * Sorts strings, numbers, dates or booleans.
 * @param  {Array}   data          Array of objects to sort
 * @param  {String}  sortKey       Key for the field to sort by
 * @param  {Boolean} isAscending   True if ascending, false otherwise.
 * @return {Array}   A new array of sorted data
 */
export const newSortDataBy = (data, sortKey, isAscending = true, sortDataType) => {
  const sortType = sortDataType || sortKeyToType[sortKey];

  switch (sortType) {
    case 'string':
      if (isAscending) return [...data.sort((a, b) => a[sortKey].localeCompare(b[sortKey]))];
      return [...data.sort((a, b) => b[sortKey].localeCompare(a[sortKey]))];
    case 'number':
      // Casts to number to cover cases where the property is a string (e.g. |serialNumber|).
      if (isAscending) return [...data.sort((a, b) => Number(a[sortKey]) - Number(b[sortKey]))];
      return [...data.sort((a, b) => Number(b[sortKey]) - Number(a[sortKey]))];
    case 'date':
      if (isAscending) return [...data.sort((a, b) => new Date(b[sortKey]) - new Date(a[sortKey]))];
      return [...data.sort((a, b) => new Date(a[sortKey]) - new Date(b[sortKey]))];
    case 'boolean':
      if (isAscending) return [...data.sort((a, b) => b[sortKey] - a[sortKey])];
      return [...data.sort((a, b) => a[sortKey] - b[sortKey])];
    default:
      throw new Error(`sortType for the field '${sortKey}' not defined`);
  }
};

export default sortDataBy;
<|endoftext|>


<commit_before>var page = div();
page.initialStyle = 'transform:scale(.9);opacity:0;';
var tags = "新歌:song/list:音乐总有新玩法,排行:rank/list:排行榜 - 酷狗音乐,歌单:plist/list:歌单 - 酷狗音乐,歌手:singer/keywords:歌手分类 - 酷狗音乐".split(",").map(function (tag, cx) {
    var [str, url, title] = tag.split(":");
    var label = createElement(div);
    label.active = function (ratio) {
        go(this.url, null, this.container);
        if (ratio === 1) {
            document.title = label.title;
            if (tags.active === this) return this.container;
            tags.active = this;
            render.refresh();
        }
        return this.container;
    };
    label.title = title;
    label.url = url;
    label.container = div();
    label.index = cx;
    text(label, str);
    return label;
});
onappend(page, function () {
    tags.active && (document.title = tags.active.title);
});
page.innerHTML = home;
render(page, {
    go,
    tags,
    tag: button,
    btn: button,
    input,
    slider(elem) {
        var pages = slider(elem, function (index, ratio) {
            if (ratio === 1) {
                state({
                    page: index
                });
            }
            var tag = tags[index];
            return tag && tag.active(ratio);
        });
        pages.go(state().page || 0);
        console.log(pages)
        return pages;
    }
});
function main() {
    return page;
}<commit_msg>左右滑动时不再进行页面重绘<commit_after>var page = div();
page.initialStyle = 'transform:scale(.9);opacity:0;';
var tags = "新歌:song/list:音乐总有新玩法,排行:rank/list:排行榜 - 酷狗音乐,歌单:plist/list:歌单 - 酷狗音乐,歌手:singer/keywords:歌手分类 - 酷狗音乐".split(",").map(function (tag, cx) {
    var [str, url, title] = tag.split(":");
    var label = createElement(div);
    label.active = function (ratio) {
        if (label.needactive) {
            delete label.needactive;
            go(this.url, null, this.container);
        }
        if (ratio === 1) {
            document.title = label.title;
            if (tags.active === this) return this.container;
            tags.active = this;
            render.refresh();
        }
        return this.container;
    };
    label.needactive = true;
    label.title = title;
    label.url = url;
    label.container = div();
    label.index = cx;
    text(label, str);
    return label;
});
onappend(page, function () {
    tags.active && (document.title = tags.active.title);
});
page.innerHTML = home;
render(page, {
    go,
    tags,
    tag: button,
    btn: button,
    input,
    slider(elem) {
        var pages = slider(elem, function (index, ratio) {
            if (ratio === 1) {
                state({
                    page: index
                });
            }
            var tag = tags[index];
            return tag && tag.active(ratio);
        });
        pages.go(state().page || 0);
        return pages;
    }
});
function main() {
    return page;
}<|endoftext|>


<commit_before>import { ObservableWrapper } from 'angular2/src/facade/async';
import { ComponentAnnotation as Component, ViewAnnotation as View, onDestroy } from 'angular2/angular2';
import { InjectAnnotation as Inject } from 'angular2/di';
import { NgIf } from 'angular2/directives';
import { DefaultValueAccessor, CheckboxControlValueAccessor, ControlDirective, ControlGroupDirective, FormBuilder, Validators } from 'angular2/forms';

import { Chores } from 'services';

@Component({
	selector: 'task',
	properties: {
		'chore': 'model'
	},
	appInjector: [
		FormBuilder,
		Chores
	],
	lifecycle: [
		onDestroy
	]
})

@View({
	templateUrl: 'components/task/task.html',
	directives: [
		DefaultValueAccessor,
		CheckboxControlValueAccessor,
		ControlDirective,
		ControlGroupDirective
	]
})

export class Task {
	constructor(@Inject(FormBuilder) builder, @Inject(Chores) chores) {
		let that = this;
		this.chores = chores;
		this.task = builder.group({
			status: [false],
			desc: ['']
		});
		this.status = this.task.controls.status;
		this.desc = this.task.controls.desc;
		this._subs = [
			ObservableWrapper.subscribe(this.status.valueChanges, function (value) {
				that.chores.update(
					that.chore.key,
					Object.assign({}, that.chore, {
						completed: value
					})
				);
			}),
			ObservableWrapper.subscribe(this.desc.valueChanges, function (value) {
				that.chores.update(
					that.chore.key,
					Object.assign({}, that.chore, {
						desc: value
					})
				);
			})
		];
	}

	set chore(value) {
		this._model = value;
		this.status.updateValue(value.completed);
	}

	get chore() {
		return this._model;
	}

	remove(event) {
		event.preventDefault();
		this.chores.remove(this.chore.key);
	}

	onDestroy() {
		for (let sub of this._subs) {
			ObservableWrapper.dispose(sub);
		}
	}
}<commit_msg>feat(task): if task desc is invalid do not update to avoid empty values<commit_after>import { ObservableWrapper } from 'angular2/src/facade/async';
import { ComponentAnnotation as Component, ViewAnnotation as View, onDestroy } from 'angular2/angular2';
import { InjectAnnotation as Inject } from 'angular2/di';
import { NgIf } from 'angular2/directives';
import { DefaultValueAccessor, CheckboxControlValueAccessor, ControlDirective, ControlGroupDirective, FormBuilder, Validators } from 'angular2/forms';

import { Chores } from 'services';

@Component({
	selector: 'task',
	properties: {
		'chore': 'model'
	},
	appInjector: [
		FormBuilder,
		Chores
	],
	lifecycle: [
		onDestroy
	]
})

@View({
	templateUrl: 'components/task/task.html',
	directives: [
		DefaultValueAccessor,
		CheckboxControlValueAccessor,
		ControlDirective,
		ControlGroupDirective
	]
})

export class Task {
	constructor(@Inject(FormBuilder) builder, @Inject(Chores) chores) {
		let that = this;
		that.chores = chores;
		that.task = builder.group({
			status: [false],
			desc: ['', Validators.required]
		});
		that.status = that.task.controls.status;
		that.desc = that.task.controls.desc;
		that._subs = [
			ObservableWrapper.subscribe(that.status.valueChanges, function (value) {
				that.chores.update(
					that.chore.key,
					Object.assign({}, that.chore, {
						completed: value
					})
				);
			}),
			ObservableWrapper.subscribe(that.desc.valueChanges, function (value) {
				if (!that.desc.valid) return;
				that.chores.update(
					that.chore.key,
					Object.assign({}, that.chore, {
						desc: value
					})
				);
			})
		];
	}

	set chore(value) {
		this._model = value;
		this.status.updateValue(value.completed);
	}

	get chore() {
		return this._model;
	}

	remove(event) {
		event.preventDefault();
		this.chores.remove(this.chore.key);
	}

	onDestroy() {
		for (let sub of this._subs) {
			ObservableWrapper.dispose(sub);
		}
	}
}<|endoftext|>


<commit_before>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

/*eslint valid-jsdoc: "off"*/
(function(CoreWM, Panel, PanelItem, Utils, API, GUI, VFS) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // ITEM
  /////////////////////////////////////////////////////////////////////////////

  /**
   * PanelItem: Buttons
   */
  function PanelItemButtons(settings) {
    PanelItem.apply(this, ['PanelItemButtons', 'Buttons', settings, {
      buttons: [
        {
          title: API._('LBL_SETTINGS'),
          icon: 'categories/applications-system.png',
          launch: 'ApplicationSettings'
        }
      ]
    }]);
  }

  PanelItemButtons.prototype = Object.create(PanelItem.prototype);
  PanelItemButtons.constructor = PanelItem;

  PanelItemButtons.prototype.init = function() {
    var self = this;
    var root = PanelItem.prototype.init.apply(this, arguments);

    this.renderButtons();

    var ghost;
    var lastTarget;
    var removeTimeout;
    var lastPadding = null;

    function clearGhost() {
      removeTimeout = clearTimeout(removeTimeout);
      ghost = Utils.$remove(ghost);
      lastTarget = null;
      if ( lastPadding !== null ) {
        self._$container.style.paddingRight = lastPadding;
      }
    }

    function createGhost(target) {
      if ( !target || !target.parentNode ) {
        return;
      }
      if ( target.tagName !== 'LI' && target.tagName !== 'UL' ) {
        return;
      }

      if ( lastPadding === null ) {
        lastPadding = self._$container.style.paddingRight;
      }

      if ( target !== lastTarget ) {
        clearGhost();

        ghost = document.createElement('li');
        ghost.className = 'Ghost';

        if ( target.tagName === 'LI' ) {
          try {
            target.parentNode.insertBefore(ghost, target);
          } catch ( e ) {}
        } else {
          target.appendChild(ghost);
        }
      }
      lastTarget = target;

      self._$container.style.paddingRight = '16px';
    }

    GUI.Helpers.createDroppable(this._$container, {
      onOver: function(ev, el, args) {
        if ( ev.target && !Utils.$hasClass(ev.target, 'Ghost') ) {
          createGhost(ev.target);
        }
      },

      onLeave: function() {
        clearTimeout(removeTimeout);
        removeTimeout = setTimeout(function() {
          clearGhost();
        }, 1000);
      },

      onDrop: function() {
        clearGhost();
      },

      onItemDropped: function(ev, el, item, args) {
        if ( item && item.data ) {
          var newPosition = 0;
          if ( Utils.$hasClass(ev.target, 'Ghost') ) {
            newPosition = Math.max(0, Utils.$index(ev.target) - 1);
          }

          if ( typeof item.data.position !== 'undefined' ) {
            self.moveButton(item.data.position, newPosition);
          } else if ( item.data.mime === 'osjs/application' ) {
            // TODO: Create at correct position
            var appName = item.data.path.split('applications:///')[1];
            self.createButton(appName);
          }
        }

        clearGhost();
      },

      onFilesDropped: function(ev, el, files, args) {
        clearGhost();
      }
    });

    return root;
  };

  PanelItemButtons.prototype.clearButtons = function() {
    Utils.$empty(this._$container);
  };

  PanelItemButtons.prototype.renderButtons = function() {
    var self = this;
    var systemButtons = {
      applications: function(ev) {
        OSjs.Applications.CoreWM.showMenu(ev);
      },
      settings: function(ev) {
        var wm = OSjs.Core.getWindowManager();
        if ( wm ) {
          wm.showSettings();
        }
      },
      exit: function(ev) {
        OSjs.API.signOut();
      }
    };

    this.clearButtons();

    (this._settings.get('buttons') || []).forEach(function(btn, idx) {
      var menu = [{
        title: 'Remove button',
        onClick: function() {
          self.removeButton(idx);
        }
      }];
      var callback = function() {
        API.launch(btn.launch);
      };

      if ( btn.system ) {
        menu = null; //systemMenu;
        callback = function(ev) {
          ev.stopPropagation();
          systemButtons[btn.system](ev);
        };
      }

      self.addButton(btn.title, btn.icon, menu, callback, idx);
    });
  };

  PanelItemButtons.prototype.removeButton = function(index) {
    var buttons = this._settings.get('buttons');
    buttons.splice(index, 1);
    this.renderButtons();

    this._settings.save();
  };

  PanelItemButtons.prototype.moveButton = function(from, to) {
    var self = this;
    var buttons = this._settings.get('buttons');

    if ( from === to || buttons.length <= 1 ) {
      return;
    }

    if ( to >= buttons.length ) {
      var k = to - buttons.length;
      while ( (k--) + 1 ) {
        buttons.push(undefined);
      }
    }

    buttons.splice(to, 0, buttons.splice(from, 1)[0]);

    this._settings.save(function() {
      self.renderButtons();
    });
  };

  PanelItemButtons.prototype.createButton = function(appName) {
    var pkg = OSjs.Core.getPackageManager().getPackage(appName);
    var buttons = this._settings.get('buttons');
    buttons.push({
      title: appName,
      icon: pkg.icon,
      launch: appName
    });

    this.renderButtons();

    this._settings.save();
  };

  PanelItemButtons.prototype.addButton = function(title, icon, menu, callback, idx) {
    var img = document.createElement('img');
    img.alt = '';
    img.src = API.getIcon(icon);

    var sel = document.createElement('li');
    sel.title = title;
    sel.setAttribute('role', 'button');
    sel.setAttribute('aria-label', title);
    sel.appendChild(img);

    Utils.$bind(sel, 'mousedown', function(ev) {
      ev.stopPropagation();
    });
    Utils.$bind(sel, 'click', callback, true);
    Utils.$bind(sel, 'contextmenu', function(ev) {
      ev.preventDefault();
      ev.stopPropagation();
      if ( menu ) {
        API.createMenu(menu, ev);
      }
    });

    GUI.Helpers.createDraggable(sel, {
      data: {
        position: idx
      }
    });

    this._$container.appendChild(sel);
  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.CoreWM = OSjs.Applications.CoreWM || {};
  OSjs.Applications.CoreWM.PanelItems = OSjs.Applications.CoreWM.PanelItems || {};
  OSjs.Applications.CoreWM.PanelItems.Buttons = PanelItemButtons;

})(OSjs.Applications.CoreWM.Class, OSjs.Applications.CoreWM.Panel, OSjs.Applications.CoreWM.PanelItem, OSjs.Utils, OSjs.API, OSjs.GUI, OSjs.VFS);
<commit_msg>CoreWM: Shortcut buttons now placed at position where dropped<commit_after>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

/*eslint valid-jsdoc: "off"*/
(function(CoreWM, Panel, PanelItem, Utils, API, GUI, VFS) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // ITEM
  /////////////////////////////////////////////////////////////////////////////

  /**
   * PanelItem: Buttons
   */
  function PanelItemButtons(settings) {
    PanelItem.apply(this, ['PanelItemButtons', 'Buttons', settings, {
      buttons: [
        {
          title: API._('LBL_SETTINGS'),
          icon: 'categories/applications-system.png',
          launch: 'ApplicationSettings'
        }
      ]
    }]);
  }

  PanelItemButtons.prototype = Object.create(PanelItem.prototype);
  PanelItemButtons.constructor = PanelItem;

  PanelItemButtons.prototype.init = function() {
    var self = this;
    var root = PanelItem.prototype.init.apply(this, arguments);

    this.renderButtons();

    var ghost;
    var lastTarget;
    var removeTimeout;
    var lastPadding = null;

    function clearGhost() {
      removeTimeout = clearTimeout(removeTimeout);
      ghost = Utils.$remove(ghost);
      lastTarget = null;
      if ( lastPadding !== null ) {
        self._$container.style.paddingRight = lastPadding;
      }
    }

    function createGhost(target) {
      if ( !target || !target.parentNode ) {
        return;
      }
      if ( target.tagName !== 'LI' && target.tagName !== 'UL' ) {
        return;
      }

      if ( lastPadding === null ) {
        lastPadding = self._$container.style.paddingRight;
      }

      if ( target !== lastTarget ) {
        clearGhost();

        ghost = document.createElement('li');
        ghost.className = 'Ghost';

        if ( target.tagName === 'LI' ) {
          try {
            target.parentNode.insertBefore(ghost, target);
          } catch ( e ) {}
        } else {
          target.appendChild(ghost);
        }
      }
      lastTarget = target;

      self._$container.style.paddingRight = '16px';
    }

    GUI.Helpers.createDroppable(this._$container, {
      onOver: function(ev, el, args) {
        if ( ev.target && !Utils.$hasClass(ev.target, 'Ghost') ) {
          createGhost(ev.target);
        }
      },

      onLeave: function() {
        clearTimeout(removeTimeout);
        removeTimeout = setTimeout(function() {
          clearGhost();
        }, 1000);
      },

      onDrop: function() {
        clearGhost();
      },

      onItemDropped: function(ev, el, item, args) {
        if ( item && item.data ) {
          var newPosition = 0;
          if ( Utils.$hasClass(ev.target, 'Ghost') ) {
            newPosition = Utils.$index(ev.target);
          }

          if ( typeof item.data.position !== 'undefined' ) {
            self.moveButton(item.data.position, newPosition - 1);
          } else if ( item.data.mime === 'osjs/application' ) {
            var appName = item.data.path.split('applications:///')[1];
            self.createButton(appName, newPosition);
          }
        }

        clearGhost();
      },

      onFilesDropped: function(ev, el, files, args) {
        clearGhost();
      }
    });

    return root;
  };

  PanelItemButtons.prototype.clearButtons = function() {
    Utils.$empty(this._$container);
  };

  PanelItemButtons.prototype.renderButtons = function() {
    var self = this;
    var systemButtons = {
      applications: function(ev) {
        OSjs.Applications.CoreWM.showMenu(ev);
      },
      settings: function(ev) {
        var wm = OSjs.Core.getWindowManager();
        if ( wm ) {
          wm.showSettings();
        }
      },
      exit: function(ev) {
        OSjs.API.signOut();
      }
    };

    this.clearButtons();

    (this._settings.get('buttons') || []).forEach(function(btn, idx) {
      var menu = [{
        title: 'Remove button',
        onClick: function() {
          self.removeButton(idx);
        }
      }];
      var callback = function() {
        API.launch(btn.launch);
      };

      if ( btn.system ) {
        menu = null; //systemMenu;
        callback = function(ev) {
          ev.stopPropagation();
          systemButtons[btn.system](ev);
        };
      }

      self.addButton(btn.title, btn.icon, menu, callback, idx);
    });
  };

  PanelItemButtons.prototype.removeButton = function(index) {
    var buttons = this._settings.get('buttons');
    buttons.splice(index, 1);
    this.renderButtons();

    this._settings.save();
  };

  PanelItemButtons.prototype.moveButton = function(from, to) {
    var self = this;
    var buttons = this._settings.get('buttons');

    if ( from === to || buttons.length <= 1 ) {
      return;
    }

    if ( to >= buttons.length ) {
      var k = to - buttons.length;
      while ( (k--) + 1 ) {
        buttons.push(undefined);
      }
    }

    buttons.splice(to, 0, buttons.splice(from, 1)[0]);

    this._settings.save(function() {
      self.renderButtons();
    });
  };

  PanelItemButtons.prototype.createButton = function(appName, position) {
    var pkg = OSjs.Core.getPackageManager().getPackage(appName);
    var buttons = this._settings.get('buttons');

    var iter = {
      title: appName,
      icon: pkg.icon,
      launch: appName
    };

    if ( !buttons.length ) {
      buttons.push(iter);
    } else {
      buttons.splice(position, 0, iter);
    }

    this.renderButtons();

    this._settings.save();
  };

  PanelItemButtons.prototype.addButton = function(title, icon, menu, callback, idx) {
    var img = document.createElement('img');
    img.alt = '';
    img.src = API.getIcon(icon);

    var sel = document.createElement('li');
    sel.title = title;
    sel.setAttribute('role', 'button');
    sel.setAttribute('aria-label', title);
    sel.appendChild(img);

    Utils.$bind(sel, 'mousedown', function(ev) {
      ev.stopPropagation();
    });
    Utils.$bind(sel, 'click', callback, true);
    Utils.$bind(sel, 'contextmenu', function(ev) {
      ev.preventDefault();
      ev.stopPropagation();
      if ( menu ) {
        API.createMenu(menu, ev);
      }
    });

    GUI.Helpers.createDraggable(sel, {
      data: {
        position: idx
      }
    });

    this._$container.appendChild(sel);
  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.CoreWM = OSjs.Applications.CoreWM || {};
  OSjs.Applications.CoreWM.PanelItems = OSjs.Applications.CoreWM.PanelItems || {};
  OSjs.Applications.CoreWM.PanelItems.Buttons = PanelItemButtons;

})(OSjs.Applications.CoreWM.Class, OSjs.Applications.CoreWM.Panel, OSjs.Applications.CoreWM.PanelItem, OSjs.Utils, OSjs.API, OSjs.GUI, OSjs.VFS);
<|endoftext|>


<commit_before>define(["dojo/_base/declare", "dojo/_base/lang", "esri", "esri/map", "esri/MapNavigationManager", "esri/MouseEvents", "esri/TouchEvents"],
function(declare, lang, esri, esriMap, MapNavigationManager, mouseEvents, touchEvents) {

	return declare("utils.KineticPanning", null, {

		// map:	esri/Map
		//		Reference the to map object
		map : null,

		// deceleration: double
		//		The multiplier that is applied to the velocity during each kinetic pan interval
		deceleration : 0.85,

		// displacementMouseMultiplier: double
		//		Multiplier for calcultaing the initial kinectic panning velocity when using mouse events.  The higher the number, the further and longer the pan will last
		//		Values 2 - 20 tend to work the best for mouse events
		displacementMouseMultiplier : 5.0,

		// displacementTouchMultiplier: double
		//		Multiplier for calcultaing the initial kinectic panning velocity when using touch events.  The higher the number, the further and longer the pan will last
		//		Values 15 - 40 tend to work the best for touch events
		displacementTouchMultiplier : 20.0,

		// minEndVelocity: double
		//		The number at which the kinetic panning will stop when below the minimum threshold
		minEndVelocity : 0.1,

		// eventModel: string
		//		The type of event model being used, set automatically.  (touch || mouse)
		eventModel : null,

		// _dragInterval: Interval
		//		The interval used for when the user is panning.  Interval is used to calculate the current velocity
		_dragInterval : null,

		// _dragIntervalDuration: int
		//		Duration of each _dragInterval
		_dragIntervalDuration : 50,

		// _kineticPanInterval: int
		//		Interval used for kinetic panning
		_kineticPanInterval : null,

		// _kineticPanIntervalDuration: int
		//		Duration of each _kineticPanInterval
		_kineticPanIntervalDuration : 15,

		// _mouseEnabled: Boolean
		//		Indicates whether the mouse events are enabled
		_mouseEnabled : false,

		// _touchEnabled: Boolean
		//		Indicates whether the touch events are enabled
		_touchEnabled : false,

		constructor : function(map) {
			this.map = map;

			this._initEventModel();

			// need to override the base _panInit to end any kinetic panning.
			// needs to be terminated before it internally calls its _initStart and _panStart
			this.map.navigationManager._panInit = lang.hitch(this, function(e) {
				var justKilled = false;
				if (this.isKineticPanning) {
					// kill kinetic panning when mouseDrag occurs
					this._kineticPanEnd();
					justKilled = true;
				}

				// call base init
				esri.MapNavigationManager.prototype._panInit.call(this.map.navigationManager, e);

				if (justKilled)
					// need to manually kickoff panStart
					this.map.navigationManager._panStart(e);
			});

			this.map.navigationManager._swipeInit = lang.hitch(this, function(e) {
				if (this.isKineticPanning) {
					// kill kinetic panning when mouseDrag occurs
					this._kineticPanEnd();
				}

				// call base init
				esri.MapNavigationManager.prototype._swipeInit.call(this.map.navigationManager, e);
			});

			this.enableMouse();
			this.enableTouch();
		},
		// _initEventModel
		//		Create touch and mouse event models.
		_initEventModel : function() {
			if (esri.isTouchEnabled) {
				this.touchEvents = new touchEvents(this.map.__container, {
					map : map
				});
				this.eventModel = "touch";
			} else {
				this.mouseEvents = new mouseEvents(this.map.__container, {
					map : map
				});
				this.eventModel = "mouse";
			}
		},
		enableTouch : function() {
			if (!this._touchEnabled) {
				this._touchEnabled = true;

				this._touchSwipeStartHandle = dojo.connect(this.touchEvents, 'onSwipeStart', this, this._onMouseDragStart);
				this._touchSwipeHandle = dojo.connect(this.touchEvents, "onSwipeMove", this, this._onMouseDrag);
				this._touchSwipeEndHandle = dojo.connect(this.touchEvents, "onSwipeEnd", this, this._onMouseDragEnd);
				this._touchSwipeExtentChangeHandle = dojo.connect(this.map, 'onExtentChange', this, this._kineticPanStart);

				this._touchSwipeStartHandle = this._touchSwipeHandle = this._touchSwipeEndHandle = this._touchSwipeExtentChangeHandle = null;
			}
		},
		disableTouch : function() {
			if (this._mouseEnabled) {
				this._mouseEnabled = false;

				dojo.disconnect(this._touchSwipeStartHandle);
				dojo.disconnect(this._touchSwipeHandle);
				dojo.disconnect(this._touchSwipeEndHandle);
				dojo.disconnect(this._touchSwipeExtentChangeHandle);

				this._mouseDragStartHandle = this._mouseDragHandle = this._mouseDragEndHandle = this._touchSwipeExtentChangeHandle = null;
			}
		},
		enableMouse : function() {
			if (!this._mouseEnabled) {
				this._mouseEnabled = true;

				this._mouseDragStartHandle = dojo.connect(this.mouseEvents, 'onMouseDragStart', this, this._onMouseDragStart);
				this._mouseDragHandle = dojo.connect(this.mouseEvents, 'onMouseDrag', this, this._onMouseDrag);
				this._mouseDragEndHandle = dojo.connect(this.mouseEvents, 'onMouseDragEnd', this, this._onMouseDragEnd);
				this._mouseExtentChangeHandle = dojo.connect(this.map, 'onExtentChange', this, this._kineticPanStart);
			}
		},
		disableMouse : function() {
			if (this._mouseEnabled) {
				this._mouseEnabled = false;

				dojo.disconnect(this._mouseDragStartHandle);
				dojo.disconnect(this._mouseDragHandle);
				dojo.disconnect(this._mouseDragEndHandle);
				dojo.disconnect(this._mouseExtentChangeHandle);

				this._mouseDragStartHandle = this._mouseDragHandle = this._mouseDragEndHandle = this._mouseExtentChangeHandle = null;
			}
		},
		// _onMouseDragStart
		//		Initialize kinetic pan properties
		_onMouseDragStart : function(e) {
			this._mouseDragEvt = this._mouseDragStartEvt = e;
			this._doKineticPanning = true;
			this._lastDragEvt = e;

			// calcute the init velocity for the kinetic panning,
			// only base it off the last interval before dragging ends
			this._dragInterval = setInterval(lang.hitch(this, function() {
				this._setInitVelocity();
			}), this._dragIntervalDuration);
		},
		// _onMouseDrag
		//		Capture mouse drag event for calculating initial kinetic pan velocity
		_onMouseDrag : function(e) {
			this._mouseDragEvt = e;
		},
		// _onMouseDragEnd
		//		Capture mouse drag end event for starting point of kinetic pan
		_onMouseDragEnd : function(e) {
			this._mouseDragEndEvt = e;
			// don't kick off pan here, introduces lag on older devices, use extentChange event instead
			//this._kineticPanStart();
		},
		// _kineticPanStart
		//		Kicks of the kinetic panning, sets needed intervals to perform animation
		_kineticPanStart : function(extent, e) {
			if (this._doKineticPanning) {
				clearInterval(this._dragInterval);

				if (this.xVelocity !== 0 && this.yVelocity !== 0) {
					var startPoint = {
						screenPoint : this._onMouseDragEndEvt ? this._onMouseDragEndEvt.screenPoint : this._mouseDragEvt.screenPoint
					};

					// manually kick off map nav panning
					this.map.navigationManager._panInit(startPoint);
					this.map.navigationManager._panStart(startPoint);

					this._doKineticPanning = false;
					this.isKineticPanning = true;

					this._curPanningPoint = {
						screenPoint : this._mouseDragStartEvt.screenPoint
					};

					this._kineticPanInterval = setInterval(lang.hitch(this, function() {
						this._kineticPan();
					}), this._kineticPanIntervalDuration);
				}
			}
		},
		// _kineticPan
		//		Performs one iteration of the kinetic panning
		_kineticPan : function() {
			// decrease velocity
			this.xVelocity *= this.deceleration;
			this.yVelocity *= this.deceleration;

			// set new points
			this._curPanningPoint.screenPoint.x += this.xVelocity;
			this._curPanningPoint.screenPoint.y += this.yVelocity;

			// do the pan
			this.map.navigationManager._pan(this._curPanningPoint);

			if (!this._continuePanning())
				this._kineticPanEnd();
		},
		// _kineticPanEnd
		//		Ends the kinetic pan animation
		_kineticPanEnd : function() {
			if (this._kineticPanInterval)
				clearInterval(this._kineticPanInterval);

			if (this._kineticTimeout)
				clearTimeout(this._kineticTimeout);

			this.isKineticPanning = false;
			this.map.navigationManager._panEnd(this._curPanningPoint);
		},
		// _continuePanning
		//		Determines if the kinnetic panning animation should continue
		//	returns:	Boolean
		_continuePanning : function() {
			return (Math.abs(this.xVelocity) > this.minEndVelocity || Math.abs(this.yVelocity) > this.minEndVelocity);
		},
		// _calculateInitVelocity
		//		Sets the starting velocity for the kinetic panning
		_setInitVelocity : function() {
			this.xVelocity = this._calculateInitVelocity(this._lastDragEvt.screenPoint.x, this._mouseDragEvt.screenPoint.x);
			this.yVelocity = this._calculateInitVelocity(this._lastDragEvt.screenPoint.y, this._mouseDragEvt.screenPoint.y);

			this._lastDragEvt = this._mouseDragEvt;
		},
		// _calculateInitVelocity
		//		Calculates the starting velocity for the kinetic panning
		_calculateInitVelocity : function(/*int*/start, /*int*/end) {
			if (start === end)
				return 0;
			else {
				var displacementMultiplier;
				if (this.eventModel === "touch")
					displacementMultiplier = this.displacementTouchMultiplier;
				else
					displacementMultiplier = this.displacementMouseMultiplier;

				return ((end - start) * displacementMultiplier) / this._dragIntervalDuration;
			}

		}
	});
});
<commit_msg>fix enable/disable touch events<commit_after>define(["dojo/_base/declare", "dojo/_base/lang", "esri", "esri/map", "esri/MapNavigationManager", "esri/MouseEvents", "esri/TouchEvents"],
function(declare, lang, esri, esriMap, MapNavigationManager, mouseEvents, touchEvents) {

	return declare("utils.KineticPanning", null, {

		// map:	esri/Map
		//		Reference the to map object
		map : null,

		// deceleration: double
		//		The multiplier that is applied to the velocity during each kinetic pan interval
		deceleration : 0.85,

		// displacementMouseMultiplier: double
		//		Multiplier for calcultaing the initial kinectic panning velocity when using mouse events.  The higher the number, the further and longer the pan will last
		//		Values 2 - 20 tend to work the best for mouse events
		displacementMouseMultiplier : 5.0,

		// displacementTouchMultiplier: double
		//		Multiplier for calcultaing the initial kinectic panning velocity when using touch events.  The higher the number, the further and longer the pan will last
		//		Values 15 - 40 tend to work the best for touch events
		displacementTouchMultiplier : 20.0,

		// minEndVelocity: double
		//		The number at which the kinetic panning will stop when below the minimum threshold
		minEndVelocity : 0.1,

		// eventModel: string
		//		The type of event model being used, set automatically.  (touch || mouse)
		eventModel : null,

		// _dragInterval: Interval
		//		The interval used for when the user is panning.  Interval is used to calculate the current velocity
		_dragInterval : null,

		// _dragIntervalDuration: int
		//		Duration of each _dragInterval
		_dragIntervalDuration : 50,

		// _kineticPanInterval: int
		//		Interval used for kinetic panning
		_kineticPanInterval : null,

		// _kineticPanIntervalDuration: int
		//		Duration of each _kineticPanInterval
		_kineticPanIntervalDuration : 15,

		// _mouseEnabled: Boolean
		//		Indicates whether the mouse events are enabled
		_mouseEnabled : false,

		// _touchEnabled: Boolean
		//		Indicates whether the touch events are enabled
		_touchEnabled : false,

		constructor : function(map) {
			this.map = map;

			this._initEventModel();

			// need to override the base _panInit to end any kinetic panning.
			// needs to be terminated before it internally calls its _initStart and _panStart
			this.map.navigationManager._panInit = lang.hitch(this, function(e) {
				var justKilled = false;
				if (this.isKineticPanning) {
					// kill kinetic panning when mouseDrag occurs
					this._kineticPanEnd();
					justKilled = true;
				}

				// call base init
				esri.MapNavigationManager.prototype._panInit.call(this.map.navigationManager, e);

				if (justKilled)
					// need to manually kickoff panStart
					this.map.navigationManager._panStart(e);
			});

			this.map.navigationManager._swipeInit = lang.hitch(this, function(e) {
				if (this.isKineticPanning) {
					// kill kinetic panning when mouseDrag occurs
					this._kineticPanEnd();
				}

				// call base init
				esri.MapNavigationManager.prototype._swipeInit.call(this.map.navigationManager, e);
			});

			this.enableMouse();
			this.enableTouch();
		},
		// _initEventModel
		//		Create touch and mouse event models.
		_initEventModel : function() {
			if (esri.isTouchEnabled) {
				this.touchEvents = new touchEvents(this.map.__container, {
					map : map
				});
				this.eventModel = "touch";
			} else {
				this.mouseEvents = new mouseEvents(this.map.__container, {
					map : map
				});
				this.eventModel = "mouse";
			}
		},
		enableTouch : function() {
			if (!this._touchEnabled) {
				this._touchEnabled = true;

				this._touchSwipeStartHandle = dojo.connect(this.touchEvents, 'onSwipeStart', this, this._onMouseDragStart);
				this._touchSwipeHandle = dojo.connect(this.touchEvents, "onSwipeMove", this, this._onMouseDrag);
				this._touchSwipeEndHandle = dojo.connect(this.touchEvents, "onSwipeEnd", this, this._onMouseDragEnd);
				this._touchSwipeExtentChangeHandle = dojo.connect(this.map, 'onExtentChange', this, this._kineticPanStart);
			}
		},
		disableTouch : function() {
			if (this._touchEnabled) {
				this._touchEnabled = false;

				dojo.disconnect(this._touchSwipeStartHandle);
				dojo.disconnect(this._touchSwipeHandle);
				dojo.disconnect(this._touchSwipeEndHandle);
				dojo.disconnect(this._touchSwipeExtentChangeHandle);

				this._touchSwipeStartHandle = this._touchSwipeHandle = this._touchSwipeEndHandle = this._touchSwipeExtentChangeHandle = null;
			}
		},
		enableMouse : function() {
			if (!this._mouseEnabled) {
				this._mouseEnabled = true;

				this._mouseDragStartHandle = dojo.connect(this.mouseEvents, 'onMouseDragStart', this, this._onMouseDragStart);
				this._mouseDragHandle = dojo.connect(this.mouseEvents, 'onMouseDrag', this, this._onMouseDrag);
				this._mouseDragEndHandle = dojo.connect(this.mouseEvents, 'onMouseDragEnd', this, this._onMouseDragEnd);
				this._mouseExtentChangeHandle = dojo.connect(this.map, 'onExtentChange', this, this._kineticPanStart);
			}
		},
		disableMouse : function() {
			if (this._mouseEnabled) {
				this._mouseEnabled = false;

				dojo.disconnect(this._mouseDragStartHandle);
				dojo.disconnect(this._mouseDragHandle);
				dojo.disconnect(this._mouseDragEndHandle);
				dojo.disconnect(this._mouseExtentChangeHandle);

				this._mouseDragStartHandle = this._mouseDragHandle = this._mouseDragEndHandle = this._mouseExtentChangeHandle = null;
			}
		},
		// _onMouseDragStart
		//		Initialize kinetic pan properties
		_onMouseDragStart : function(e) {
			this._mouseDragEvt = this._mouseDragStartEvt = e;
			this._doKineticPanning = true;
			this._lastDragEvt = e;

			// calcute the init velocity for the kinetic panning,
			// only base it off the last interval before dragging ends
			this._dragInterval = setInterval(lang.hitch(this, function() {
				this._setInitVelocity();
			}), this._dragIntervalDuration);
		},
		// _onMouseDrag
		//		Capture mouse drag event for calculating initial kinetic pan velocity
		_onMouseDrag : function(e) {
			this._mouseDragEvt = e;
		},
		// _onMouseDragEnd
		//		Capture mouse drag end event for starting point of kinetic pan
		_onMouseDragEnd : function(e) {
			this._mouseDragEndEvt = e;
			// don't kick off pan here, introduces lag on older devices, use extentChange event instead
			//this._kineticPanStart();
		},
		// _kineticPanStart
		//		Kicks of the kinetic panning, sets needed intervals to perform animation
		_kineticPanStart : function(extent, e) {
			if (this._doKineticPanning) {
				clearInterval(this._dragInterval);

				if (this.xVelocity !== 0 && this.yVelocity !== 0) {
					var startPoint = {
						screenPoint : this._onMouseDragEndEvt ? this._onMouseDragEndEvt.screenPoint : this._mouseDragEvt.screenPoint
					};

					// manually kick off map nav panning
					this.map.navigationManager._panInit(startPoint);
					this.map.navigationManager._panStart(startPoint);

					this._doKineticPanning = false;
					this.isKineticPanning = true;

					this._curPanningPoint = {
						screenPoint : this._mouseDragStartEvt.screenPoint
					};

					this._kineticPanInterval = setInterval(lang.hitch(this, function() {
						this._kineticPan();
					}), this._kineticPanIntervalDuration);
				}
			}
		},
		// _kineticPan
		//		Performs one iteration of the kinetic panning
		_kineticPan : function() {
			// decrease velocity
			this.xVelocity *= this.deceleration;
			this.yVelocity *= this.deceleration;

			// set new points
			this._curPanningPoint.screenPoint.x += this.xVelocity;
			this._curPanningPoint.screenPoint.y += this.yVelocity;

			// do the pan
			this.map.navigationManager._pan(this._curPanningPoint);

			if (!this._continuePanning())
				this._kineticPanEnd();
		},
		// _kineticPanEnd
		//		Ends the kinetic pan animation
		_kineticPanEnd : function() {
			if (this._kineticPanInterval)
				clearInterval(this._kineticPanInterval);

			if (this._kineticTimeout)
				clearTimeout(this._kineticTimeout);

			this.isKineticPanning = false;
			this.map.navigationManager._panEnd(this._curPanningPoint);
		},
		// _continuePanning
		//		Determines if the kinnetic panning animation should continue
		//	returns:	Boolean
		_continuePanning : function() {
			return (Math.abs(this.xVelocity) > this.minEndVelocity || Math.abs(this.yVelocity) > this.minEndVelocity);
		},
		// _calculateInitVelocity
		//		Sets the starting velocity for the kinetic panning
		_setInitVelocity : function() {
			this.xVelocity = this._calculateInitVelocity(this._lastDragEvt.screenPoint.x, this._mouseDragEvt.screenPoint.x);
			this.yVelocity = this._calculateInitVelocity(this._lastDragEvt.screenPoint.y, this._mouseDragEvt.screenPoint.y);

			this._lastDragEvt = this._mouseDragEvt;
		},
		// _calculateInitVelocity
		//		Calculates the starting velocity for the kinetic panning
		_calculateInitVelocity : function(/*int*/start, /*int*/end) {
			if (start === end)
				return 0;
			else {
				var displacementMultiplier;
				if (this.eventModel === "touch")
					displacementMultiplier = this.displacementTouchMultiplier;
				else
					displacementMultiplier = this.displacementMouseMultiplier;

				return ((end - start) * displacementMultiplier) / this._dragIntervalDuration;
			}

		}
	});
});
<|endoftext|>


<commit_before>// @flow
import Stylis from 'stylis'
import _insertRulePlugin from 'stylis-rule-sheet'
import type { Interpolation } from '../types'

// NOTE: This stylis instance is only used to split rules from SSR'd style tags
const stylisSplitter = new Stylis({
  global: false,
  cascade: true,
  keyframe: false,
  prefix: false,
  compress: false,
  semicolon: true,
})

const stylis = new Stylis({
  global: false,
  cascade: true,
  keyframe: false,
  prefix: true,
  compress: false,
  semicolon: false, // NOTE: This means "autocomplete missing semicolons"
})

// Wrap `insertRulePlugin to build a list of rules,
// and then make our own plugin to return the rules. This
// makes it easier to hook into the existing SSR architecture

let parsingRules = []
// eslint-disable-next-line consistent-return
const returnRulesPlugin = context => {
  if (context === -2) {
    const parsedRules = parsingRules
    parsingRules = []
    return parsedRules
  }
}

const parseRulesPlugin = _insertRulePlugin(rule => {
  parsingRules.push(rule)
})

stylis.use([parseRulesPlugin, returnRulesPlugin])
stylisSplitter.use([parseRulesPlugin, returnRulesPlugin])

const stringifyRules = (
  rules: Array<Interpolation>,
  selector: ?string,
  prefix: ?string
): Array<string> => {
  const flatCSS = rules.join('').replace(/^\s*\/\/.*$/gm, '') // replace JS comments

  const cssStr =
    selector && prefix ? `${prefix} ${selector} { ${flatCSS} }` : flatCSS

  return stylis(prefix || !selector ? '' : selector, cssStr)
}

export const splitByRules = (css: string): Array<string> =>
  stylisSplitter('', css)

export default stringifyRules
<commit_msg>cache JS comment regex<commit_after>// @flow
import Stylis from 'stylis'
import _insertRulePlugin from 'stylis-rule-sheet'
import type { Interpolation } from '../types'

const COMMENT_REGEX = /^\s*\/\/.*$/gm

// NOTE: This stylis instance is only used to split rules from SSR'd style tags
const stylisSplitter = new Stylis({
  global: false,
  cascade: true,
  keyframe: false,
  prefix: false,
  compress: false,
  semicolon: true,
})

const stylis = new Stylis({
  global: false,
  cascade: true,
  keyframe: false,
  prefix: true,
  compress: false,
  semicolon: false, // NOTE: This means "autocomplete missing semicolons"
})

// Wrap `insertRulePlugin to build a list of rules,
// and then make our own plugin to return the rules. This
// makes it easier to hook into the existing SSR architecture

let parsingRules = []
// eslint-disable-next-line consistent-return
const returnRulesPlugin = context => {
  if (context === -2) {
    const parsedRules = parsingRules
    parsingRules = []
    return parsedRules
  }
}

const parseRulesPlugin = _insertRulePlugin(rule => {
  parsingRules.push(rule)
})

stylis.use([parseRulesPlugin, returnRulesPlugin])
stylisSplitter.use([parseRulesPlugin, returnRulesPlugin])

const stringifyRules = (
  rules: Array<Interpolation>,
  selector: ?string,
  prefix: ?string
): Array<string> => {
  const flatCSS = rules.join('').replace(COMMENT_REGEX, '') // replace JS comments

  const cssStr =
    selector && prefix ? `${prefix} ${selector} { ${flatCSS} }` : flatCSS

  return stylis(prefix || !selector ? '' : selector, cssStr)
}

export const splitByRules = (css: string): Array<string> =>
  stylisSplitter('', css)

export default stringifyRules
<|endoftext|>


<commit_before>// test/spec for backend/servers/mcapi/db/model/project.js

'use strict';

let assert = require('chai').assert;
let connection = require('rethinkdbdash')({
    db: process.env.MCDB || 'materialscommons',
    port: process.env.MCDB_PORT || 30815
});

let projects = require('../projects')(connection);

describe('Test of db/model projects - ', function() {
    describe('return all projects: ', function() {
        it("should not be null", function () {
            let projectListDeffered = projects.all();
            projectListDeffered.then(function (theList) {
                let name = "not found";
                assert.isNotNull(theList, "Project list should exist");
            });
        });
    });

    describe('find project - ', function() {
        it ("project named 'Test' should exist" , function() {
            let projectListDeffered = projects.all();
            projectListDeffered.then(function(theList){
                let name = "not found";
                assert.isNotNull(theList, "Project list should exist");
                for (let project of theList) {
                    if (project.name == 'Test') {
                        name = project.name;
                    }
                }
                assert.equal(name,"Test","missing 'Test' project");
            });
        });
    });
});
<commit_msg>Changed projects-spec to use yield - working<commit_after>// test/spec for backend/servers/mcapi/db/model/project.js

'use strict';

let assert = require('chai').assert;
let connection = require('rethinkdbdash')({
    db: process.env.MCDB || 'materialscommons',
    port: process.env.MCDB_PORT || 30815
});

let projects = require('../projects')(connection);

describe('Test of db/model projects - ', function () {
    describe('return all projects: ', function () {
        it("should not be null", function () {
            let projectListDeffered = projects.all();
            projectListDeffered.then(function (theList) {
                let name = "not found";
                assert.isNotNull(theList, "Project list should exist");
            });
        });
    });

    describe('find project - ', function () {
        it("project named 'Test' should exist", function () {
            let projectListDeffered = projects.all();
            projectListDeffered.then(function (theList) {
                let name = "not found";
                assert.isNotNull(theList, "Project list should exist");
                for (let project of theList) {
                    if (project.name == 'Test') {
                        name = project.name;
                    }
                }
                assert.equal(name, "Test", "missing 'Test' project");
            });
        });
        it("project named 'Test' should exist - starred", function*() {
            let projectsList = yield projects.all();
            let name = "not found";
            for (let project of projectsList) {
                if (project.name == 'Test') {
                    name = project.name;
                }
            }
            assert.equal(name, "Test", "missing 'Test' project");
        });
    });
});
<|endoftext|>


<commit_before>import {Validation} from '../validation/validation';

export class Debouncer{
  constructor(debounceTimeout){
    this.currentFunction = null;
    this.debounceTimeout = debounceTimeout;
  }

  debounce(func)
  {
    this.currentFunction = func;
    setTimeout(() => {
        if(func !== null && func !== undefined)
        {
          if(func === this.currentFunction) {
            this.currentFunction = null;
            func();
          }
        }
    }, this.debounceTimeout);
  }
}
<commit_msg>Remove unneeded (circular) dependency.<commit_after>export class Debouncer{
  constructor(debounceTimeout){
    this.currentFunction = null;
    this.debounceTimeout = debounceTimeout;
  }

  debounce(func)
  {
    this.currentFunction = func;
    setTimeout(() => {
        if(func !== null && func !== undefined)
        {
          if(func === this.currentFunction) {
            this.currentFunction = null;
            func();
          }
        }
    }, this.debounceTimeout);
  }
}
<|endoftext|>