<commit_before>/*
 * touchmouse.js
 * Fabian Irsara
 * Copyright 2015, Licensed GPL & MIT
 */
define(['../../config'], function(config){

  /**
   * handles mouse and touch events
   * dispatches tap and doubletap events
   * dispatches idle and active events
   * unifies mouse and touch events to touchmouse events
   * checks if click and tap events really are click events by tracking moved positions and time between last click
   *
   * @example
   * document.getElementById('slider').addEventListener('touchmousedown', down);
   * document.getElementById('slider').addEventListener('tap', tap);
   * document.getElementById('slider').addEventListener('doubletap', doubletap);
   * window.addEventListener('idle', idle);
   * window.addEventListener('active', active);
   *
   * @namespace touchmouse
   * @memberof dom.utils
   **/

  // event constants that should be dispatched
  var EVENTS = {
    DOWN: 'touchmousedown',
    UP: 'touchmouseup',
    MOVE: 'touchmousemove',
    TAP: 'tap',
    DOUBLE_TAP: 'doubletap',
    IDLE: 'idle',
    ACTIVE: 'active'
  };

  // tracked touches via pointer id
  var trackedTouches = [];

  // tracked positions (for pointer events only first finger gets tracked)
  var trackedPositions = {start: {}, end: {}, hadMultiple: false};

  // stored idle timeout id for dispatching idle event, gets resetted on every action
  var idleTimeout = null;

  // stores if was idle before when reactivating
  var wasIdle = false;

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onMouseEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onMouseEvent = function(event) {
    var type, evt;

    switch (event.type) {
      case 'mousedown': type = EVENTS.DOWN; break;
      case 'mouseup':   type = EVENTS.UP;   break;
      case 'mousemove': type = EVENTS.MOVE; break;
      default:
        return;
    }

    // create appropriate touchmouse event based on original event
    evt = _createEvent(type, event, event.pageX, event.pageY, -1);

    // dispatch touchmouse event on target
    event.target.dispatchEvent(evt);

    if (type === EVENTS.DOWN) {
      // store start mouse position
      trackedPositions.start = {x: evt.pageX, y: evt.pageY};
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: evt.pageX, y: evt.pageY};

      // check if it was a tap
      checkTap(event.target, event, evt.pageX, evt.pageY, -1);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onTouchEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onTouchEvent = function(event) {
    var type, i, _len, target, touch, touches, activeTouches, k, evt;

    switch (event.type) {
      case 'touchstart':  type = EVENTS.DOWN; break;
      case 'touchend':    type = EVENTS.UP;   break;
      case 'touchcancel': type = EVENTS.UP;   break;
      case 'touchmove':   type = EVENTS.MOVE; break;
      default:
        return;
    }

    // store changed touches
    touches = event.changedTouches;

    // loop through all events and create and dispatch event for each changed pointer id
    // NOTE: this is not so performant but easier to use in subclasses
    for (i = 0, _len = touches.length; i < _len; i++) {
      // store current touch
      touch = touches[i];

      // create appropriate event
      evt = _createEvent(type, event, touch.pageX, touch.pageY, touch.identifier);

      // if already has a tracked target for current pointerID
      // NOTE: maybe always used document.elementFromPoint as touch could move over multiple objects?
      if (trackedTouches[touch.identifier]) {
        // get cached, tracked target
        target = trackedTouches[touch.identifier].target;
      } else {
        // find target through document.elementFromPoint and cache target
        target = document.elementFromPoint(touch.pageX, touch.pageY);
        trackedTouches[touch.identifier] = {target: target};
      }

      // dispatch event on target
      target.dispatchEvent(evt);
    }

    // delete unused tracked touches
    if (type === EVENTS.UP) {
      var activeTouchIdentifiers = [];

      for (i = 0, _len = event.touches.length; i < _len; i++) {
        activeTouchIdentifiers.push(event.touches[i].identifier);
      }

      for (k in trackedTouches) {
        if (activeTouchIdentifiers.indexOf(k) === -1) {
          // !!!!! also important now for remote tracking!!
          // TODO: IMPORTANT: dispatch mouse up for every deleted tracked touch that was not on changedTouches!
          delete trackedTouches[k];
        }
      }
    }

    // if finger count changed (via touchstart or touchend)
    if (type === EVENTS.DOWN || type === EVENTS.UP) {
      // calculate active touches
      activeTouches = 0;

      for (k in trackedTouches) {
        if (trackedTouches[k].target) {
          activeTouches++;
        }
      }
    }

    if (type === EVENTS.DOWN) {
      // store if had multiple fingers throughout transformations before ending a touch (i.e. before tapping)
      trackedPositions.hadMultiple = activeTouches > 1;

      // if it was the first finger
      if (activeTouches === 1) {
        // store start mouse position
        trackedPositions.start = {x: touches[0].pageX, y: touches[0].pageY};
      }
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: touches[0].pageX, y: touches[0].pageY};

      // check if it was a tap on last found target
      checkTap(target, event, touches[0].pageX, touches[0].pageY, touches[0].identifier);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * dispatches active event on window
   *
   * @method dispatchActive
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchActive = function(){
    wasIdle = false;

    var event = new Event(EVENTS.ACTIVE, {
      bubbles: true,
      cancelable: true
    });

    window.dispatchEvent(event);
  };

  /**
   * dispatches idle event on window
   *
   * @method dispatchIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchIdle = function(){
    // check if was not idle before (prevent internal logic bug)
    if (wasIdle) return;
    wasIdle = true;

    var event = new Event(EVENTS.IDLE, {
      bubbles: true,
      cancelable: true
    });

    window.dispatchEvent(event);
  };

  /**
   * checks if event was a valid tap
   * i.e. if not moved too far and did not have multiple fingers
   * also checks for double taps
   *
   * @method checkTap
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {DomElement} target that was tapped and stores multiple tap counts
   **/
  var checkTap = function(target, originalEvent, x, y, pointerID){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (! (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20)
    ) {
      var evt = null;
      var wasDoubleTap = false;

      var now = Date.now();

      // if tapped again within 350 ms
      if (now - target._lastTapTime < 350) {
        // and is an even tap count
        if ((target._taps + 1) % 2 === 0) {
          // create double tap event
          wasDoubleTap = true;
        }
      } else {
        // otherwise reset taps
        target._taps = 0;
      }

      // store last tap time on dom element
      target._lastTapTime = now;

      // increment tap count on dom element
      target._taps++;

      // if it was a valid tap: dispatch event, pass tap count to event
      evt = _createEvent(EVENTS.TAP, originalEvent, x, y, pointerID);
      evt.taps = target._taps;
      target.dispatchEvent(evt);

      // if also was a double tap
      if (wasDoubleTap) {
        // dispatch a double tap event on target, pass tap count to event
        evt = _createEvent(EVENTS.DOUBLE_TAP, originalEvent, x, y, pointerID);
        evt.taps = target._taps;
        target.dispatchEvent(evt);
      }
    }
  };

  /**
   * checks moved distance and if had multiple fingers
   * prevents event if distance was too long
   *
   * @method onClickEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from click listener
   **/
  var onClickEvent = function(event){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20
    ) {
      event.stopPropagation();
    }
  };

  /**
   * creates a custom event and returns it
   *
   * @method _createEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {String} type of event that should be created
   * @param {Event} originalEvent (if available) to store for later usage
   * @param {Number} x position of event
   * @param {Number} y position of event
   * @param {Number} pointerID that was used (multiple fingers)
   * @returns {Event} the created event
   **/
  var _createEvent = function(type, originalEvent, x, y, pointerID) {
    var event = new Event(type, {
      bubbles: true,
      cancelable: true
    });

    event.originalEvent = originalEvent;
    event.pageX = x;
    event.pageY = y;
    event.pointerID = pointerID;

    return event;
  };

  /**
   * resets idle state and dispatches active on window if was idle before
   *
   * @method _resetIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var _resetIdle = function(){
    // if was idle before: dispatch active event
    if (wasIdle) dispatchActive();

    // reset idle timeout (idle every 15 seconds)
    if (idleTimeout) clearTimeout(idleTimeout);
    idleTimeout = setTimeout(dispatchIdle, 15000);
  };

  // check if supports touch events
  if (config.isTouch || config.trackTouch) {
    // if it does: listen to appropriate touch events in whole window
    window.addEventListener('touchstart', onTouchEvent);
    window.addEventListener('touchmove', onTouchEvent);
    window.addEventListener('touchend', onTouchEvent);
    window.addEventListener('touchcancel', onTouchEvent);
  }

  if (! config.isTouch || config.trackMouse) {
    // otherwise check mouse events and convert them
    window.addEventListener('mousedown', onMouseEvent);
    window.addEventListener('mouseup', onMouseEvent);
    window.addEventListener('mousemove', onMouseEvent);
  }

  // TODO: is buggy, maybe leave mouse events as they are and only check for tap events as they are used internally and not by libraries?
  // check for click events (if moved while trying to click: do not dispatch click)
  //document.addEventListener('click', onClickEvent, true);

  _resetIdle();

});
<commit_msg>prevent default events<commit_after>/*
 * touchmouse.js
 * Fabian Irsara
 * Copyright 2015, Licensed GPL & MIT
 */
define(['../../config'], function(config){

  /**
   * handles mouse and touch events
   * dispatches tap and doubletap events
   * dispatches idle and active events
   * unifies mouse and touch events to touchmouse events
   * checks if click and tap events really are click events by tracking moved positions and time between last click
   *
   * @example
   * document.getElementById('slider').addEventListener('touchmousedown', down);
   * document.getElementById('slider').addEventListener('tap', tap);
   * document.getElementById('slider').addEventListener('doubletap', doubletap);
   * window.addEventListener('idle', idle);
   * window.addEventListener('active', active);
   *
   * @namespace touchmouse
   * @memberof dom.utils
   **/

  // event constants that should be dispatched
  var EVENTS = {
    DOWN: 'touchmousedown',
    UP: 'touchmouseup',
    MOVE: 'touchmousemove',
    TAP: 'tap',
    DOUBLE_TAP: 'doubletap',
    IDLE: 'idle',
    ACTIVE: 'active'
  };

  // tracked touches via pointer id
  var trackedTouches = [];

  // tracked positions (for pointer events only first finger gets tracked)
  var trackedPositions = {start: {}, end: {}, hadMultiple: false};

  // stored idle timeout id for dispatching idle event, gets resetted on every action
  var idleTimeout = null;

  // stores if was idle before when reactivating
  var wasIdle = false;

  // if tracking both events prevent them by default
  var preventEvents = config.trackTouch && config.trackMouse;

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onMouseEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onMouseEvent = function(event) {
    if (preventEvents) event.preventDefault();

    var type, evt;

    switch (event.type) {
      case 'mousedown': type = EVENTS.DOWN; break;
      case 'mouseup':   type = EVENTS.UP;   break;
      case 'mousemove': type = EVENTS.MOVE; break;
      default:
        return;
    }

    // create appropriate touchmouse event based on original event
    evt = _createEvent(type, event, event.pageX, event.pageY, -1);

    // dispatch touchmouse event on target
    event.target.dispatchEvent(evt);

    if (type === EVENTS.DOWN) {
      // store start mouse position
      trackedPositions.start = {x: evt.pageX, y: evt.pageY};
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: evt.pageX, y: evt.pageY};

      // check if it was a tap
      checkTap(event.target, event, evt.pageX, evt.pageY, -1);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onTouchEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onTouchEvent = function(event) {
    if (preventEvents) event.preventDefault();

    var type, i, _len, target, touch, touches, activeTouches, k, evt;

    switch (event.type) {
      case 'touchstart':  type = EVENTS.DOWN; break;
      case 'touchend':    type = EVENTS.UP;   break;
      case 'touchcancel': type = EVENTS.UP;   break;
      case 'touchmove':   type = EVENTS.MOVE; break;
      default:
        return;
    }

    // store changed touches
    touches = event.changedTouches;

    // loop through all events and create and dispatch event for each changed pointer id
    // NOTE: this is not so performant but easier to use in subclasses
    for (i = 0, _len = touches.length; i < _len; i++) {
      // store current touch
      touch = touches[i];

      // create appropriate event
      evt = _createEvent(type, event, touch.pageX, touch.pageY, touch.identifier);

      // if already has a tracked target for current pointerID
      // NOTE: maybe always used document.elementFromPoint as touch could move over multiple objects?
      if (trackedTouches[touch.identifier]) {
        // get cached, tracked target
        target = trackedTouches[touch.identifier].target;
      } else {
        // find target through document.elementFromPoint and cache target
        target = document.elementFromPoint(touch.pageX, touch.pageY);
        trackedTouches[touch.identifier] = {target: target};
      }

      // dispatch event on target
      target.dispatchEvent(evt);
    }

    // delete unused tracked touches
    if (type === EVENTS.UP) {
      var activeTouchIdentifiers = [];

      for (i = 0, _len = event.touches.length; i < _len; i++) {
        activeTouchIdentifiers.push(event.touches[i].identifier);
      }

      for (k in trackedTouches) {
        if (activeTouchIdentifiers.indexOf(k) === -1) {
          // !!!!! also important now for remote tracking!!
          // TODO: IMPORTANT: dispatch mouse up for every deleted tracked touch that was not on changedTouches!
          delete trackedTouches[k];
        }
      }
    }

    // if finger count changed (via touchstart or touchend)
    if (type === EVENTS.DOWN || type === EVENTS.UP) {
      // calculate active touches
      activeTouches = 0;

      for (k in trackedTouches) {
        if (trackedTouches[k].target) {
          activeTouches++;
        }
      }
    }

    if (type === EVENTS.DOWN) {
      // store if had multiple fingers throughout transformations before ending a touch (i.e. before tapping)
      trackedPositions.hadMultiple = activeTouches > 1;

      // if it was the first finger
      if (activeTouches === 1) {
        // store start mouse position
        trackedPositions.start = {x: touches[0].pageX, y: touches[0].pageY};
      }
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: touches[0].pageX, y: touches[0].pageY};

      // check if it was a tap on last found target
      checkTap(target, event, touches[0].pageX, touches[0].pageY, touches[0].identifier);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * dispatches active event on window
   *
   * @method dispatchActive
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchActive = function(){
    wasIdle = false;

    var event = new Event(EVENTS.ACTIVE, {
      bubbles: true,
      cancelable: true
    });

    window.dispatchEvent(event);
  };

  /**
   * dispatches idle event on window
   *
   * @method dispatchIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchIdle = function(){
    // check if was not idle before (prevent internal logic bug)
    if (wasIdle) return;
    wasIdle = true;

    var event = new Event(EVENTS.IDLE, {
      bubbles: true,
      cancelable: true
    });

    window.dispatchEvent(event);
  };

  /**
   * checks if event was a valid tap
   * i.e. if not moved too far and did not have multiple fingers
   * also checks for double taps
   *
   * @method checkTap
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {DomElement} target that was tapped and stores multiple tap counts
   **/
  var checkTap = function(target, originalEvent, x, y, pointerID){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (! (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20)
    ) {
      var evt = null;
      var wasDoubleTap = false;

      var now = Date.now();

      // if tapped again within 350 ms
      if (now - target._lastTapTime < 350) {
        // and is an even tap count
        if ((target._taps + 1) % 2 === 0) {
          // create double tap event
          wasDoubleTap = true;
        }
      } else {
        // otherwise reset taps
        target._taps = 0;
      }

      // store last tap time on dom element
      target._lastTapTime = now;

      // increment tap count on dom element
      target._taps++;

      // if it was a valid tap: dispatch event, pass tap count to event
      evt = _createEvent(EVENTS.TAP, originalEvent, x, y, pointerID);
      evt.taps = target._taps;
      target.dispatchEvent(evt);

      // if also was a double tap
      if (wasDoubleTap) {
        // dispatch a double tap event on target, pass tap count to event
        evt = _createEvent(EVENTS.DOUBLE_TAP, originalEvent, x, y, pointerID);
        evt.taps = target._taps;
        target.dispatchEvent(evt);
      }
    }
  };

  /**
   * checks moved distance and if had multiple fingers
   * prevents event if distance was too long
   *
   * @method onClickEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from click listener
   **/
  var onClickEvent = function(event){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20
    ) {
      event.stopPropagation();
    }
  };

  /**
   * creates a custom event and returns it
   *
   * @method _createEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {String} type of event that should be created
   * @param {Event} originalEvent (if available) to store for later usage
   * @param {Number} x position of event
   * @param {Number} y position of event
   * @param {Number} pointerID that was used (multiple fingers)
   * @returns {Event} the created event
   **/
  var _createEvent = function(type, originalEvent, x, y, pointerID) {
    var event = new Event(type, {
      bubbles: true,
      cancelable: true
    });

    event.originalEvent = originalEvent;
    event.pageX = x;
    event.pageY = y;
    event.pointerID = pointerID;

    return event;
  };

  /**
   * resets idle state and dispatches active on window if was idle before
   *
   * @method _resetIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var _resetIdle = function(){
    // if was idle before: dispatch active event
    if (wasIdle) dispatchActive();

    // reset idle timeout (idle every 15 seconds)
    if (idleTimeout) clearTimeout(idleTimeout);
    idleTimeout = setTimeout(dispatchIdle, 15000);
  };

  // check if supports touch events
  if (config.isTouch || config.trackTouch) {
    // if it does: listen to appropriate touch events in whole window
    window.addEventListener('touchstart', onTouchEvent);
    window.addEventListener('touchmove', onTouchEvent);
    window.addEventListener('touchend', onTouchEvent);
    window.addEventListener('touchcancel', onTouchEvent);
  }

  if (! config.isTouch || config.trackMouse) {
    // otherwise check mouse events and convert them
    window.addEventListener('mousedown', onMouseEvent);
    window.addEventListener('mouseup', onMouseEvent);
    window.addEventListener('mousemove', onMouseEvent);
  }

  // TODO: is buggy, maybe leave mouse events as they are and only check for tap events as they are used internally and not by libraries?
  // check for click events (if moved while trying to click: do not dispatch click)
  //document.addEventListener('click', onClickEvent, true);

  _resetIdle();

});
<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

/**
 * This module contains the handlers for native platform events.
 * From here, the dispatcher is called to create unified pointer events.
 * Included are touch events (v1), mouse events, and MSPointerEvents.
 */
(function(scope) {
  var dispatcher = scope.dispatcher;

  // only activate if this platform does not have pointer events
  if (window.navigator.pointerEnabled === undefined) {
    Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enumerable: true});

    if (window.navigator.msPointerEnabled) {
      var tp = window.navigator.msMaxTouchPoints;
      Object.defineProperty(window.navigator, 'maxTouchPoints', {
        value: tp,
        enumerable: true
      });
      dispatcher.registerSource('ms', scope.msEvents);
    } else {
      dispatcher.registerSource('mouse', scope.mouseEvents);
      if (window.ontouchstart !== undefined) {
        dispatcher.registerSource('touch', scope.touchEvents);
      }
    }

    dispatcher.register(document);
  }
})(window.PointerEventsPolyfill);
<commit_msg>Remove deprecated navigator.pointerEnabled<commit_after>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

/**
 * This module contains the handlers for native platform events.
 * From here, the dispatcher is called to create unified pointer events.
 * Included are touch events (v1), mouse events, and MSPointerEvents.
 */
(function(scope) {
  var dispatcher = scope.dispatcher;

  // only activate if this platform does not have pointer events
  if (!window.PointerEvent) {

    if (window.navigator.msPointerEnabled) {
      var tp = window.navigator.msMaxTouchPoints;
      Object.defineProperty(window.navigator, 'maxTouchPoints', {
        value: tp,
        enumerable: true
      });
      dispatcher.registerSource('ms', scope.msEvents);
    } else {
      dispatcher.registerSource('mouse', scope.mouseEvents);
      if (window.ontouchstart !== undefined) {
        dispatcher.registerSource('touch', scope.touchEvents);
      }
    }

    dispatcher.register(document);
  }
})(window.PointerEventsPolyfill);
<|endoftext|>


<commit_before>'use strict';

(function (angular) {
    'use strict';

    var thisModule = angular.module('appFiles',
        [
            'ngMaterial',
            'ui.router', 'ui.utils', 'ngResource', 'ngAria', 'ngCookies', 'ngSanitize', 'ngMessages',
            'ngMaterial', 'wu.masonry', 'LocalStorageModule', 'ngAnimate',

            'pipServices',
            'pipTheme.Default', 'pipTheme.BootBarn', 'pipTheme',

            'pipFiles', 'pipFiles.Templates',  //'pipButtons',

            'appFiles.UploadFiles', 'appFiles.Progress', 'appFiles.SuccessUpload',
             'appFiles.FailUpload', 'appFiles.StartUpload'
        ]
    );

    var content = [
            {
                title: 'Upload', state: 'upload', url: '/upload',
                controller: 'UploadController', templateUrl: 'files_sample/files.html'
            },{
                title: 'Start upload', state: 'start', url: '/start',
                controller: 'FailStartController', templateUrl: 'files_start/files_start.html'
            }, {
                title: 'Progress', state: 'progress', url: '/progress',
                controller: 'ProgressController', templateUrl: 'files_upload/files_upload.html'
            },{
                title: 'Success upload', state: 'success', url: '/success',
                controller: 'SuccessUploadController', templateUrl: 'files_success/files_success.html'
            },{
                title: 'Fail upload', state: 'fail', url: '/fail',
                controller: 'FailUploadController', templateUrl: 'files_fail/files_fail.html'
            }
        ];

    // Configure application services before start
    thisModule.config(
        function ($stateProvider, $urlRouterProvider, $mdIconProvider,
                  $compileProvider, $httpProvider) {

            $compileProvider.debugInfoEnabled(false);
            $httpProvider.useApplyAsync(true);

            var contentItem, i;

            $mdIconProvider.iconSet('icons', 'images/icons.svg', 512);

            for (i = 0; i < content.length; i++) {
                contentItem = content[i];
                $stateProvider.state(contentItem.state, contentItem);
            }

            $urlRouterProvider.otherwise('/upload');
        }
    );

    thisModule.controller('pipSampleController',
        function ($scope, $rootScope, $injector, $state, $mdSidenav, $timeout, $mdTheming, $mdMedia, localStorageService) {

            var pipTranslate = $injector.has('pipTranslate') ? $injector.get('pipTranslate') : null,
                // appThemesDefault = $injector.has('appThemesDefault') ? $injector.get('appThemesDefault') : null,
                pipTheme = $injector.has('pipTheme') ? $injector.get('pipTheme') : null;

            $scope.isTranslated = !!pipTranslate;
            $scope.isTheme = !!pipTheme;
            $scope.$mdMedia = $mdMedia;

            $rootScope.$theme = localStorageService.get('theme') || 'blue';
            if ($scope.isTheme) {
                $scope.themes = _.keys(_.omit($mdTheming.THEMES, 'default'));
            } else {
                $scope.themes = [];
            }

            $scope.languages = ['en', 'ru'];
            if (!$rootScope.$language) {
                $rootScope.$language = 'en';
            }

            $scope.content = content;
            $scope.menuOpened = false;

            // Update page after language changed
            $rootScope.$on('languageChanged', function(event) {
                $state.reload();
            });

            // Update page after theme changed
            $rootScope.$on('themeChanged', function(event) {
                $state.reload();
            });

            $scope.onSwitchPage = function (state) {
                $mdSidenav('left').close();
                $state.go(state);
            };

            $scope.onThemeClick = function(theme) {
                console.log('onThemeClick');
                if ($scope.isTheme) {
                    console.log('onThemeClick1');
                    setTimeout(function () {
                        pipTheme.use(theme, false, false);
                        $rootScope.$theme = theme;
                        $rootScope.$apply();
                    }, 0);
                }
            };

            $scope.onToggleMenu = function () {
                $mdSidenav('left').toggle();
            };

            $scope.onLanguageClick = function(language) {
                console.log('onLanguageClick');
                if (pipTranslate) {
                    console.log('onLanguageClick1', language);
                    setTimeout(function () {
                        pipTranslate.use(language);
                        $rootScope.$apply();
                    }, 0);
                }

            };

            $scope.isActiveState = function (state) {
                return $state.current.name == state;
            };

        }
    );

})(window.angular);

/*
 var content = [
     {
        title: 'Upload', state: 'upload', url: '/upload',
        controller: 'UploadController', templateUrl: 'files_sample/files.html'
     }
];

function configFiles ($stateProvider, $urlRouterProvider, $mdIconProvider,
                  $compileProvider, $httpProvider) {

            $compileProvider.debugInfoEnabled(false);
            $httpProvider.useApplyAsync(true);

            var contentItem, i;

            $mdIconProvider.iconSet('icons', 'images/icons.svg', 512);

            for (i = 0; i < content.length; i++) {
                contentItem = content[i];
                $stateProvider.state(contentItem.state, contentItem);
            }

            $urlRouterProvider.otherwise('/files');
        }

class PortalController {

    constructor(
        $scope, $rootScope, $injector, $state, $mdSidenav, $timeout, $mdTheming, $mdMedia, localStorageService
    ) {

  var pipTranslate = $injector.has('pipTranslate') ? $injector.get('pipTranslate') : null,
                // appThemesDefault = $injector.has('appThemesDefault') ? $injector.get('appThemesDefault') : null,
                pipTheme = $injector.has('pipTheme') ? $injector.get('pipTheme') : null;

            $scope.isTranslated = !!pipTranslate;
            $scope.isTheme = !!pipTheme;
            $scope.$mdMedia = $mdMedia;

            $rootScope.$theme = localStorageService.get('theme') || 'blue';
            if ($scope.isTheme) {
                $scope.themes = _.keys(_.omit($mdTheming.THEMES, 'default'));
            } else {
                $scope.themes = [];
            }

            $scope.languages = ['en', 'ru'];
            if (!$rootScope.$language) {
                $rootScope.$language = 'en';
            }

            $scope.content = content;
            $scope.menuOpened = false;

            // Update page after language changed
            $rootScope.$on('languageChanged', function(event) {
                $state.reload();
            });

            // Update page after theme changed
            $rootScope.$on('themeChanged', function(event) {
                $state.reload();
            });

            $scope.onSwitchPage = function (state) {
                $mdSidenav('left').close();
                $state.go(state);
            };

            $scope.onThemeClick = function(theme) {
                console.log('onThemeClick');
                if ($scope.isTheme) {
                    console.log('onThemeClick1');
                    setTimeout(function () {
                        pipTheme.use(theme, false, false);
                        $rootScope.$theme = theme;
                        $rootScope.$apply();
                    }, 0);
                }
            };

            $scope.onToggleMenu = function () {
                $mdSidenav('left').toggle();
            };

            $scope.onLanguageClick = function(language) {
                console.log('onLanguageClick');
                if (pipTranslate) {
                    console.log('onLanguageClick1', language);
                    setTimeout(function () {
                        pipTranslate.use(language);
                        $rootScope.$apply();
                    }, 0);
                }

            };

            $scope.isActiveState = function (state) {
                return $state.current.name == state;
            };

    }

}

angular
    .module('appFiles', [
        'ngMaterial',
            'ui.router', 'ui.utils', 'ngResource', 'ngAria', 'ngCookies', 'ngSanitize', 'ngMessages',
            'ngMaterial', 'wu.masonry', 'LocalStorageModule', 'ngAnimate',

            'pipServices',
            'pipTheme.Default', 'pipTheme.BootBarn', 'pipTheme',

            'pipFiles', 'pipFiles.Templates',  'pipButtons',

            'appFiles.UploadFiles'
    ])
    .config(configFiles)
    .controller('pipSampleController', PortalController);
*/<commit_msg>[Samples] change items in samples<commit_after>'use strict';

(function (angular) {
    'use strict';

    var thisModule = angular.module('appFiles',
        [
            'ngMaterial',
            'ui.router', 'ui.utils', 'ngResource', 'ngAria', 'ngCookies', 'ngSanitize', 'ngMessages',
            'ngMaterial', 'wu.masonry', 'LocalStorageModule', 'ngAnimate',

            'pipServices',
            'pipTheme.Default', 'pipTheme.BootBarn', 'pipTheme',

            'pipFiles', 'pipFiles.Templates',  //'pipButtons',

            'appFiles.UploadFiles', 'appFiles.Progress', 'appFiles.SuccessUpload',
             'appFiles.FailUpload', 'appFiles.StartUpload'
        ]
    );

    var content = [
            {
                title: 'Upload', state: 'upload', url: '/upload',
                controller: 'UploadController', templateUrl: 'files_sample/files.html'
            },{
                title: 'Progress', state: 'progress', url: '/progress',
                controller: 'ProgressController', templateUrl: 'files_upload/files_upload.html'
            },
            {
                title: 'Start upload', state: 'start', url: '/start',
                controller: 'FailStartController', templateUrl: 'files_start/files_start.html'
            },{
                title: 'Success upload', state: 'success', url: '/success',
                controller: 'SuccessUploadController', templateUrl: 'files_success/files_success.html'
            },{
                title: 'Fail upload', state: 'fail', url: '/fail',
                controller: 'FailUploadController', templateUrl: 'files_fail/files_fail.html'
            }
        ];

    // Configure application services before start
    thisModule.config(
        function ($stateProvider, $urlRouterProvider, $mdIconProvider,
                  $compileProvider, $httpProvider) {

            $compileProvider.debugInfoEnabled(false);
            $httpProvider.useApplyAsync(true);

            var contentItem, i;

            $mdIconProvider.iconSet('icons', 'images/icons.svg', 512);

            for (i = 0; i < content.length; i++) {
                contentItem = content[i];
                $stateProvider.state(contentItem.state, contentItem);
            }

            $urlRouterProvider.otherwise('/upload');
        }
    );

    thisModule.controller('pipSampleController',
        function ($scope, $rootScope, $injector, $state, $mdSidenav, $timeout, $mdTheming, $mdMedia, localStorageService) {

            var pipTranslate = $injector.has('pipTranslate') ? $injector.get('pipTranslate') : null,
                // appThemesDefault = $injector.has('appThemesDefault') ? $injector.get('appThemesDefault') : null,
                pipTheme = $injector.has('pipTheme') ? $injector.get('pipTheme') : null;

            $scope.isTranslated = !!pipTranslate;
            $scope.isTheme = !!pipTheme;
            $scope.$mdMedia = $mdMedia;

            $rootScope.$theme = localStorageService.get('theme') || 'blue';
            if ($scope.isTheme) {
                $scope.themes = _.keys(_.omit($mdTheming.THEMES, 'default'));
            } else {
                $scope.themes = [];
            }

            $scope.languages = ['en', 'ru'];
            if (!$rootScope.$language) {
                $rootScope.$language = 'en';
            }

            $scope.content = content;
            $scope.menuOpened = false;

            // Update page after language changed
            $rootScope.$on('languageChanged', function(event) {
                $state.reload();
            });

            // Update page after theme changed
            $rootScope.$on('themeChanged', function(event) {
                $state.reload();
            });

            $scope.onSwitchPage = function (state) {
                $mdSidenav('left').close();
                $state.go(state);
            };

            $scope.onThemeClick = function(theme) {
                console.log('onThemeClick');
                if ($scope.isTheme) {
                    console.log('onThemeClick1');
                    setTimeout(function () {
                        pipTheme.use(theme, false, false);
                        $rootScope.$theme = theme;
                        $rootScope.$apply();
                    }, 0);
                }
            };

            $scope.onToggleMenu = function () {
                $mdSidenav('left').toggle();
            };

            $scope.onLanguageClick = function(language) {
                console.log('onLanguageClick');
                if (pipTranslate) {
                    console.log('onLanguageClick1', language);
                    setTimeout(function () {
                        pipTranslate.use(language);
                        $rootScope.$apply();
                    }, 0);
                }

            };

            $scope.isActiveState = function (state) {
                return $state.current.name == state;
            };

        }
    );

})(window.angular);

/*
 var content = [
     {
        title: 'Upload', state: 'upload', url: '/upload',
        controller: 'UploadController', templateUrl: 'files_sample/files.html'
     }
];

function configFiles ($stateProvider, $urlRouterProvider, $mdIconProvider,
                  $compileProvider, $httpProvider) {

            $compileProvider.debugInfoEnabled(false);
            $httpProvider.useApplyAsync(true);

            var contentItem, i;

            $mdIconProvider.iconSet('icons', 'images/icons.svg', 512);

            for (i = 0; i < content.length; i++) {
                contentItem = content[i];
                $stateProvider.state(contentItem.state, contentItem);
            }

            $urlRouterProvider.otherwise('/files');
        }

class PortalController {

    constructor(
        $scope, $rootScope, $injector, $state, $mdSidenav, $timeout, $mdTheming, $mdMedia, localStorageService
    ) {

  var pipTranslate = $injector.has('pipTranslate') ? $injector.get('pipTranslate') : null,
                // appThemesDefault = $injector.has('appThemesDefault') ? $injector.get('appThemesDefault') : null,
                pipTheme = $injector.has('pipTheme') ? $injector.get('pipTheme') : null;

            $scope.isTranslated = !!pipTranslate;
            $scope.isTheme = !!pipTheme;
            $scope.$mdMedia = $mdMedia;

            $rootScope.$theme = localStorageService.get('theme') || 'blue';
            if ($scope.isTheme) {
                $scope.themes = _.keys(_.omit($mdTheming.THEMES, 'default'));
            } else {
                $scope.themes = [];
            }

            $scope.languages = ['en', 'ru'];
            if (!$rootScope.$language) {
                $rootScope.$language = 'en';
            }

            $scope.content = content;
            $scope.menuOpened = false;

            // Update page after language changed
            $rootScope.$on('languageChanged', function(event) {
                $state.reload();
            });

            // Update page after theme changed
            $rootScope.$on('themeChanged', function(event) {
                $state.reload();
            });

            $scope.onSwitchPage = function (state) {
                $mdSidenav('left').close();
                $state.go(state);
            };

            $scope.onThemeClick = function(theme) {
                console.log('onThemeClick');
                if ($scope.isTheme) {
                    console.log('onThemeClick1');
                    setTimeout(function () {
                        pipTheme.use(theme, false, false);
                        $rootScope.$theme = theme;
                        $rootScope.$apply();
                    }, 0);
                }
            };

            $scope.onToggleMenu = function () {
                $mdSidenav('left').toggle();
            };

            $scope.onLanguageClick = function(language) {
                console.log('onLanguageClick');
                if (pipTranslate) {
                    console.log('onLanguageClick1', language);
                    setTimeout(function () {
                        pipTranslate.use(language);
                        $rootScope.$apply();
                    }, 0);
                }

            };

            $scope.isActiveState = function (state) {
                return $state.current.name == state;
            };

    }

}

angular
    .module('appFiles', [
        'ngMaterial',
            'ui.router', 'ui.utils', 'ngResource', 'ngAria', 'ngCookies', 'ngSanitize', 'ngMessages',
            'ngMaterial', 'wu.masonry', 'LocalStorageModule', 'ngAnimate',

            'pipServices',
            'pipTheme.Default', 'pipTheme.BootBarn', 'pipTheme',

            'pipFiles', 'pipFiles.Templates',  'pipButtons',

            'appFiles.UploadFiles'
    ])
    .config(configFiles)
    .controller('pipSampleController', PortalController);
*/<|endoftext|>


<commit_before>'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Created by desaroger on 25/02/17.
 */

var _ = require('lodash');
var co = require('co');
var childProcess = require('child_process');
var WebhookServer = require('./WebhookServer');

var _require = require('./utils'),
    log = _require.log,
    c = _require.c;

var Pm2Module = function () {
    function Pm2Module() {
        var processes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

        _classCallCheck(this, Pm2Module);

        options.routes = Pm2Module._parseProcesses(processes);
        this.routes = options.routes;
        this.webhookServer = new WebhookServer(options);
    }

    _createClass(Pm2Module, [{
        key: 'start',
        value: function start() {
            var _this = this;

            return this.webhookServer.start().then(function () {
                var msg = 'Started. Routes:\n';
                _.forOwn(_this.routes, function (route, name) {
                    msg += ' - ' + name + ': ' + JSON.stringify(route) + '\n';
                });
                log(msg);
            });
        }
    }, {
        key: 'stop',
        value: function stop() {
            return this.webhookServer.stop().then(function () {
                log('Stopped.');
            });
        }

        /**
         * Converts an array of PM2 processes to an object structured
         * for the WebhookServer routes. It internally uses the _parseProcess
         * method
         *
         * Example 1:
         * - input:
         * [
         *      { pm2_env: { env_hook: { name: 'api', type: 'bitbucket' } } },
         *      { pm2_env: { env_hook: { name: 'panel', type: 'github' } } }
         * ]
         * - output:
         * {
         *      api: { type: 'bitbucket' },
         *      panel: { type: 'github' }
         * }
         *
         * @param processes
         * @returns {*}
         * @private
         */

    }], [{
        key: '_parseProcesses',
        value: function _parseProcesses(processes) {
            return processes.map(function (p) {
                return Pm2Module._parseProcess(p);
            }).filter(function (p) {
                return !!p;
            }).reduce(function (routes, app) {
                routes[app.name] = app;
                delete app.name;
                return routes;
            }, {});
        }

        /**
         * Converts a PM2 process object to an object for WebhookServer
         * route.
         *
         * Example 1:
         * - input: { pm2_env: { env_hook: { name: 'api', type: 'bitbucket' } } }
         * - output: { name: 'api', type: 'bitbucket' }
         * Example 2:
         * - input: { pm2_env: { env_hook: { type: 'bitbucket' } } }
         * - output: { name: 'unknown', type: 'bitbucket' }
         *
         * @param app The Pm2 process
         * @returns {object|null} The route object, or null if invalid
         * @private
         */

    }, {
        key: '_parseProcess',
        value: function _parseProcess(app) {
            // Check data
            if (!app) {
                return null;
            }
            var processOptions = _.get(app, 'pm2_env.env_hook');
            if (!processOptions) {
                console.log('nope');
                return null;
            }
            console.log('options', processOptions);
            console.log('');
            var data = _.get(app, 'pm2_env.env_hook');
            if (data === true) {
                data = {};
            }

            // Data to WebhookServer route
            var self = this;
            var name = app.name || 'unknown';
            var commandOptions = Object.assign({}, { cwd: data.cwd || app.pm_cwd }, data.commandOptions || {});
            var route = {
                name: name,
                type: data.type,
                method: c(regeneratorRuntime.mark(function _callee(payload) {
                    var err;
                    return regeneratorRuntime.wrap(function _callee$(_context) {
                        while (1) {
                            switch (_context.prev = _context.next) {
                                case 0:
                                    log('Parsed payload: ' + JSON.stringify(payload));
                                    _context.prev = 1;

                                    if (!data.command) {
                                        _context.next = 6;
                                        break;
                                    }

                                    log('Running command: ' + data.command);
                                    _context.next = 6;
                                    return self._runCommand(data.command, commandOptions);

                                case 6:
                                    _context.next = 13;
                                    break;

                                case 8:
                                    _context.prev = 8;
                                    _context.t0 = _context['catch'](1);
                                    err = _context.t0.message || _context.t0;

                                    log('Error on "' + name + '" route: ' + err, 2);
                                    throw _context.t0;

                                case 13:
                                case 'end':
                                    return _context.stop();
                            }
                        }
                    }, _callee, this, [[1, 8]]);
                }))
            };
            route = cleanObj(route);

            return route;
        }

        /**
         * Runs a line command.
         *
         * @param {String} command The line to execute
         * @param {Object} options The object options
         * @returns {Promise<code>} The code of the error, or a void fulfilled promise
         * @private
         */

    }, {
        key: '_runCommand',
        value: function _runCommand(command) {
            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

            _.defaults(options, {
                env: process.env,
                shell: true
            });
            return new Promise(function (resolve, reject) {
                var child = childProcess.spawn('eval', [command], options);
                child.on('close', function (code) {
                    if (!code) {
                        resolve();
                    } else {
                        reject(code);
                    }
                });
            });
        }
    }]);

    return Pm2Module;
}();

module.exports = Pm2Module;

function cleanObj(obj) {
    return _(obj).omitBy(_.isUndefined).value();
}<commit_msg>[wip] Tests on real webhook<commit_after>'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Created by desaroger on 25/02/17.
 */

var _ = require('lodash');
var co = require('co');
var childProcess = require('child_process');
var WebhookServer = require('./WebhookServer');

var _require = require('./utils'),
    log = _require.log,
    c = _require.c;

var Pm2Module = function () {
    function Pm2Module() {
        var processes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

        _classCallCheck(this, Pm2Module);

        options.routes = Pm2Module._parseProcesses(processes);
        this.routes = options.routes;
        this.webhookServer = new WebhookServer(options);
    }

    _createClass(Pm2Module, [{
        key: 'start',
        value: function start() {
            var _this = this;

            return this.webhookServer.start().then(function () {
                var msg = 'Started. Routes:\n';
                _.forOwn(_this.routes, function (route, name) {
                    msg += ' - ' + name + ': ' + JSON.stringify(route) + '\n';
                });
                log(msg);
            });
        }
    }, {
        key: 'stop',
        value: function stop() {
            return this.webhookServer.stop().then(function () {
                log('Stopped.');
            });
        }

        /**
         * Converts an array of PM2 processes to an object structured
         * for the WebhookServer routes. It internally uses the _parseProcess
         * method
         *
         * Example 1:
         * - input:
         * [
         *      { pm2_env: { env_hook: { name: 'api', type: 'bitbucket' } } },
         *      { pm2_env: { env_hook: { name: 'panel', type: 'github' } } }
         * ]
         * - output:
         * {
         *      api: { type: 'bitbucket' },
         *      panel: { type: 'github' }
         * }
         *
         * @param processes
         * @returns {*}
         * @private
         */

    }], [{
        key: '_parseProcesses',
        value: function _parseProcesses(processes) {
            return processes.map(function (p) {
                return Pm2Module._parseProcess(p);
            }).filter(function (p) {
                return !!p;
            }).reduce(function (routes, app) {
                routes[app.name] = app;
                delete app.name;
                return routes;
            }, {});
        }

        /**
         * Converts a PM2 process object to an object for WebhookServer
         * route.
         *
         * Example 1:
         * - input: { pm2_env: { env_hook: { name: 'api', type: 'bitbucket' } } }
         * - output: { name: 'api', type: 'bitbucket' }
         * Example 2:
         * - input: { pm2_env: { env_hook: { type: 'bitbucket' } } }
         * - output: { name: 'unknown', type: 'bitbucket' }
         *
         * @param app The Pm2 process
         * @returns {object|null} The route object, or null if invalid
         * @private
         */

    }, {
        key: '_parseProcess',
        value: function _parseProcess(app) {
            // Check data
            if (!app) {
                return null;
            }
            var config = _.get(app, 'pm2_env.env_hook');
            if (!config) {
                log('No options found for "' + app.name + '" route');
                return null;
            }
            if (config === true) {
                config = {};
            }

            // Config to WebhookServer route
            var self = this;
            var name = app.name || 'unknown';
            var commandOptions = Object.assign({}, { cwd: config.cwd || app.pm_cwd }, config.commandOptions || {});
            var route = {
                name: name,
                type: config.type,
                method: c(regeneratorRuntime.mark(function _callee(payload) {
                    var err;
                    return regeneratorRuntime.wrap(function _callee$(_context) {
                        while (1) {
                            switch (_context.prev = _context.next) {
                                case 0:
                                    log('Parsed payload: ' + JSON.stringify(payload));
                                    _context.prev = 1;

                                    if (!config.command) {
                                        _context.next = 6;
                                        break;
                                    }

                                    log('Running command: ' + config.command);
                                    _context.next = 6;
                                    return self._runCommand(config.command, commandOptions);

                                case 6:
                                    _context.next = 13;
                                    break;

                                case 8:
                                    _context.prev = 8;
                                    _context.t0 = _context['catch'](1);
                                    err = _context.t0.message || _context.t0;

                                    log('Error on "' + name + '" route: ' + err, 2);
                                    throw _context.t0;

                                case 13:
                                case 'end':
                                    return _context.stop();
                            }
                        }
                    }, _callee, this, [[1, 8]]);
                }))
            };
            route = cleanObj(route);

            return route;
        }

        /**
         * Runs a line command.
         *
         * @param {String} command The line to execute
         * @param {Object} options The object options
         * @returns {Promise<code>} The code of the error, or a void fulfilled promise
         * @private
         */

    }, {
        key: '_runCommand',
        value: function _runCommand(command) {
            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

            _.defaults(options, {
                env: process.env,
                shell: true
            });
            return new Promise(function (resolve, reject) {
                var child = childProcess.spawn('eval', [command], options);
                child.on('close', function (code) {
                    if (!code) {
                        resolve();
                    } else {
                        reject(code);
                    }
                });
            });
        }
    }]);

    return Pm2Module;
}();

module.exports = Pm2Module;

function cleanObj(obj) {
    return _(obj).omitBy(_.isUndefined).value();
}<|endoftext|>


<commit_before>/*! Angulocity 0.1.0. (C) 2015 John Cui. MIT @license: en.wikipedia.org/wiki/MIT_License */
/*jshint bitwise: false*/
;(function (window, undefined) {
  'use strict';

  /* Create some shortcut references to the libraries */
  var a = window.angular,
      v = window.Velocity || window.jQuery.Velocity,
      $ = $ ? $ : window.jQuery;

  /* Generate some error messages in the console if Velocity or Velocity UI is not found */
  if (!v) {
    console.error('Angulocity: Velocity animation engine is not found. Animations are disabled.');
    v = a.noop;
  } else if (!v.RegisterEffect) {
    console.error('Angulocity: Velocity UI Pack is not found. Additional animation effects will not be available.');
  }

  /**
   * Setup Velocity options based on attributes passed to the
   * current element.
   *
   * @param   mixed   scope   Scope used to evaluate angular attribure expressions
   * @param   mixed   iAttrs  Attribute list
   * @param   bool    bIn     True if animating "In", false if animating "Out"
   *
   * @return  mixed           Velocity options object
   *
   */
  function getNgvOptions (scope, iAttrs, bIn) {
    var options = {
      /* Velocity's default options */
      duration: iAttrs.ngvDuration ? iAttrs.ngvDuration : 400,
      delay: iAttrs.ngvDelay ? scope.$eval(iAttrs.ngvDelay) : false,
      easing: iAttrs.ngvEasing ? iAttrs.ngvEasing : 'easeInOutQuart',
      queue: iAttrs.ngvQueue ? iAttrs.ngvQueue : undefined,
      begin: iAttrs.ngvBegin ? scope.$eval(iAttrs.ngvBegin) : undefined,
      progress: iAttrs.ngvProgress ? scope.$eval(iAttrs.ngvProgress) : undefined,
      complete: iAttrs.ngvComplete ? scope.$eval(iAttrs.ngvComplete) : undefined,
      display: iAttrs.ngvDisplay ? iAttrs.ngvDisplay : undefined,
      visibility: iAttrs.ngvVisibility ? iAttrs.ngvVisibility : undefined,
      loop: iAttrs.ngvLoop ? scope.$eval(iAttrs.ngvLoop) : undefined,
      stagger: iAttrs.ngvStagger ? scope.$eval(iAttrs.ngvStagger) : undefined,
      drag: iAttrs.ngvDrag ? scope.$eval(iAttrs.ngvDrag) : undefined,
      mobileHA: iAttrs.ngvMobileHa ? scope.$eval(iAttrs.ngvMobileHa) :  true
    };

    /* Alter some options based on whether animating "In" or "Out" */
    if (bIn === true) {
      options.display = iAttrs.ngvInDisplay ? iAttrs.ngvInDisplay : options.display;
      options.visibility = iAttrs.ngvInVisibility ? iAttrs.ngvInVisibility : options.visibility;
      options.duration = iAttrs.ngvInDuration ? iAttrs.ngvInDuration : options.duration;
      options.delay = iAttrs.ngvInDelay ? iAttrs.ngvInDelay : options.delay;
    } else if (bIn === false) {
      options.display = iAttrs.ngvOutDisplay ? iAttrs.ngvOutDisplay : options.display;
      options.visibility = iAttrs.ngvOutVisibility ? iAttrs.ngvOutVisibility : options.visibility;
      options.duration = iAttrs.ngvOutDuration ? iAttrs.ngvOutDuration : options.duration;
      options.delay = iAttrs.ngvOutDelay ? iAttrs.ngvOutDelay : options.delay;
    }

    return options;
  }

  /**
   * Utility function to generate hash for class names.
   *
   * @param   string  klass   Whitespace separated class values
   *
   * @return  string          Hashed class values
   *
   */
  function getNgvClass(klass) {
    var i, j, x, c, s;
    klass = klass.split(/\s/);
    for (i = 0; i < klass.length; i++) {
      x = 0;
      s = 'ngv' + klass[i].toLowerCase();
      for (j = 0; j < s.length; j++) {
          c = s.charCodeAt(i);
          x = ((x<<5)-x)+c;
      }
      klass[i] = 'ngv' + Math.abs(x).toString(16);
    }
    return klass.join(' ');
  }

  /**
   * Get collection of nodes within an element via selector
   *
   * @param   element iElement  Root element node containing the collection
   * @param   string  selector  Query selector for finding child elements
   *
   * @return  array             Node collection
   *
   */
  function getNgvCollection(iElement, selector) {
    var m = /^ngv:(\w+?)$/.exec(selector);
    if (m) {
      return a.element(iElement[0].querySelectorAll('.' + getNgvClass(m[1])));
    } else {
      return a.element(iElement[0].querySelectorAll(selector));
    }
  }

  /**
   * Angulocity Module
   *
   * @ngmodule Angulocity
   *
   */
  a.module('Angulocity', [])
  .provider('$ngvAnimator', function ngvAnimatorProvider() {
    var defaults = {

    };

    this.defaults = defaults;
    this.RegisterEffect = a.isDefined(v.RegisterEffect) ? v.RegisterEffect : a.noop;
    this.$get = [function () {
      return null;
    }];
  })
  /**
   * @ngdoc directive
   * @name  ngvSlide
   *
   */
  .directive('ngvSlide', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = iAttrs.ngvRepeat !== 'false';
        var options;

        // If animation switch provided
        if (iAttrs.ngvSlide) {
          scope.$watch(iAttrs.ngvSlide, function(n, o) {
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                iElement.css({display: options.display || 'inherited', opacity: 1});
              } else {
                iElement.css({display: options.display || 'none', opacity: 0});
              }
            } else {
              if (n) {
                v(iElement, 'stop');
                v(iElement, 'slideDown', options);
              } else {
                v(iElement, 'stop');
                v(iElement, 'slideUp', options);
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(iElement, 'slideDown', options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(iElement, 'slideUp', options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvFade
   *
   */
  .directive('ngvFade', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = iAttrs.ngvRepeat !== 'false';
        var options;

        // If animation switch provided
        if (iAttrs.ngvFade) {
          scope.$watch(iAttrs.ngvFade, function(n, o) {
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                iElement.css({display: options.display || 'inherited', opacity: 1});
              } else {
                iElement.css({display: options.display || 'none', opacity: 0});
              }
            } else {
              if (n) {
                v(iElement, 'stop');
                v(iElement, 'fadeIn', options);
              } else {
                v(iElement, 'stop');
                v(iElement, 'fadeOut', options);
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(iElement, 'fadeIn', options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(iElement, 'fadeOut', options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvClass
   *
   */
  .directive('ngvClass', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        iElement.addClass(getNgvClass(iAttrs.ngvClass));
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvCollection
   *
   */
  .directive('ngvCollection', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        var collection;
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = iAttrs.ngvRepeat !== 'false',
            effect,
            animated = false;
        var options;
        /* Attempt to evaluate effect */
        if (iAttrs.ngvEffect) {
          effect = scope.$eval(iAttrs.ngvEffect);
          if (!effect) {
            effect = iAttrs.ngvEffect;
          }
        } else {
          effect = 'fade';
        }

        if (iAttrs.ngvToggle && effect) {
          scope.$watch(iAttrs.ngvToggle, function(n, o) {
            collection = iAttrs.ngvCollection ? getNgvCollection(iElement, iAttrs.ngvCollection) : iElement.children();
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                collection.css({display: options.display || 'inherited', opacity: 1});
              } else {
                collection.css({display: options.display || 'none', opacity: 0});
              }
            } else {
              v(collection, 'stop');
              if (a.isString(effect)) {
                v(collection, effect+(n ? 'In' : 'Out'), options);
              } else {
                if (animated) {
                  v(collection, 'reverse', options);
                } else {
                  v(collection, effect, options);
                  animated = true;
                }
              }
            }
          });
        } else if (iAttrs.ngvAnimate && effect) {
          options = getNgvOptions(scope, iAttrs);
          ngvIn = scope.$watch(iAttrs.ngvAnimate, function (n) {
            if (n) {
              v(collection, effect, options);
              if (!repeat) {
                ngvIn();
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(collection, effect, options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(collection, effect, options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvElement
   *
   */
  .directive('ngvElement', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = iAttrs.ngvRepeat !== 'false',
            effect,
            animated = false;
        var options;
        /* Attempt to evaluate effect */
        if (iAttrs.ngvEffect) {
          effect = scope.$eval(iAttrs.ngvEffect);
          if (!effect) {
            effect = iAttrs.ngvEffect;
          }
        } else {
          effect = 'fade';
        }

        if (iAttrs.ngvElement) {
          iElement.addClass(getNgvClass(iAttrs.ngvElement));
        }

        /* Set up watchers depending on element attributes passed */
        if (iAttrs.ngvToggle && effect) {
          scope.$watch(iAttrs.ngvToggle, function(n, o) {
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                iElement.css({display: options.display || 'inherited', opacity: 1});
              } else {
                iElement.css({display: options.display || 'none', opacity: 0});
              }
            } else {
              v(iElement, 'stop');
              if (a.isString(effect)) {
                v(iElement, effect+(n ? 'In' : 'Out'), options);
              } else {
                if (animated) {
                  v(iElement, 'reverse', options);
                } else {
                  v(iElement, effect, options);
                  animated = true;
                }
              }
            }
          });
        } else if (iAttrs.ngvAnimate && effect) {
          options = getNgvOptions(scope, iAttrs);
          ngvIn = scope.$watch(iAttrs.ngvAnimate, function (n) {
            if (n) {
              v(iElement, effect, options);
              if (!repeat) {
                ngvIn();
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(iElement, effect, options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(iElement, effect, options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  ;
})(window, void 0);
<commit_msg>Redefined usage<commit_after>/*! Angulocity 0.1.0. (C) 2015 John Cui. MIT @license: en.wikipedia.org/wiki/MIT_License */
/*jshint bitwise: false*/
;(function (window, undefined) {
  'use strict';

  /* Create some shortcut references to the libraries */
  var a = window.angular,
      v = window.Velocity || window.jQuery.Velocity,
      $ = $ ? $ : window.jQuery;

  /* Generate some error messages in the console if Velocity or Velocity UI is not found */
  if (!v) {
    console.error('Angulocity: Velocity animation engine is not found. Animations are disabled.');
    v = a.noop;
  } else if (!v.RegisterEffect) {
    console.error('Angulocity: Velocity UI Pack is not found. Additional animation effects will not be available.');
  }

  /* Detect IE and add appropriate angular ie shims */
  if (/MSIE/.test(window.navigator.userAgent)) {
    window.document.createElement('ngv-element');
    window.document.createElement('ngv-collection');
    window.document.createElement('ngv-animator');
  }

  /**
   * Setup Velocity options based on attributes passed to the
   * current element.
   *
   * @param   mixed   scope   Scope used to evaluate angular attribure expressions
   * @param   mixed   iAttrs  Attribute list
   * @param   bool    bIn     True if animating "In", false if animating "Out"
   *
   * @return  mixed           Velocity options object
   *
   */
  function getNgvOptions (scope, iAttrs, bIn) {
    var options = {
      /* Velocity's default options */
      duration: iAttrs.ngvDuration ? iAttrs.ngvDuration : 400,
      delay: iAttrs.ngvDelay ? scope.$eval(iAttrs.ngvDelay) : false,
      easing: iAttrs.ngvEasing ? iAttrs.ngvEasing : 'easeInOutQuart',
      queue: iAttrs.ngvQueue ? iAttrs.ngvQueue : undefined,
      begin: iAttrs.ngvBegin ? scope.$eval(iAttrs.ngvBegin) : undefined,
      progress: iAttrs.ngvProgress ? scope.$eval(iAttrs.ngvProgress) : undefined,
      complete: iAttrs.ngvComplete ? scope.$eval(iAttrs.ngvComplete) : undefined,
      display: iAttrs.ngvDisplay ? iAttrs.ngvDisplay : undefined,
      visibility: iAttrs.ngvVisibility ? iAttrs.ngvVisibility : undefined,
      loop: iAttrs.ngvLoop ? scope.$eval(iAttrs.ngvLoop) : undefined,
      stagger: iAttrs.ngvStagger ? scope.$eval(iAttrs.ngvStagger) : undefined,
      drag: iAttrs.ngvDrag ? scope.$eval(iAttrs.ngvDrag) : undefined,
      mobileHA: iAttrs.ngvMobileHa ? scope.$eval(iAttrs.ngvMobileHa) :  true
    };

    /* Alter some options based on whether animating "In" or "Out" */
    if (bIn === true) {
      options.display = iAttrs.ngvInDisplay ? iAttrs.ngvInDisplay : options.display;
      options.visibility = iAttrs.ngvInVisibility ? iAttrs.ngvInVisibility : options.visibility;
      options.duration = iAttrs.ngvInDuration ? iAttrs.ngvInDuration : options.duration;
      options.delay = iAttrs.ngvInDelay ? iAttrs.ngvInDelay : options.delay;
    } else if (bIn === false) {
      options.display = iAttrs.ngvOutDisplay ? iAttrs.ngvOutDisplay : options.display;
      options.visibility = iAttrs.ngvOutVisibility ? iAttrs.ngvOutVisibility : options.visibility;
      options.duration = iAttrs.ngvOutDuration ? iAttrs.ngvOutDuration : options.duration;
      options.delay = iAttrs.ngvOutDelay ? iAttrs.ngvOutDelay : options.delay;
    }

    return options;
  }

  /**
   * Utility function to generate hash
   *
   * @param   string  s       String to perform has on
   *
   * @return  string          Hashed value of string
   */
  function getNgvHash(s) {
    var i = 0, x = 0, c;
    for (; i < s.length; i++) {
      c = s.charCodeAt(i);
      x = ((x<<5)-x)+c;
    }
    x |= 0;
    return x.toString(16);
  }
  /**
   * Utility function to generate hash for class names.
   *
   * @param   string  klass   Whitespace separated class values
   *
   * @return  string          Hashed class values
   *
   */
  function getNgvClass(klass) {
    var i;
    klass = klass.trim().split(/\s/);
    for (i = 0; i < klass.length; i++) {
      klass[i] = 'ngv' + getNgvHash('ngv' + klass[i].toLowerCase());
    }
    return klass.join(' ');
  }

  /**
   * Get collection of nodes within an element via selector
   *
   * @param   element iElement  Root element node containing the collection
   * @param   string  selector  Query selector for finding child elements
   *
   * @return  array             Node collection
   *
   */
  function getNgvCollection(iElement, selector) {
    var selectors,
        patt = /(.*?).ngv\((\w+)\)/,
        m;
    if (selector) {
      selectors = selector.trim().split(/\s*,\s*/);
      for (var i = 0; i < selectors.length; i++) {
        m = patt.exec(selectors[i]);
        if (m) {
          selectors[i] = m[1] + '.' + getNgvClass(m[2]);
        }
      }
      selector = selectors.join(',');
      return a.element(iElement[0].querySelectorAll(selector));
    } else {
      return iElement.children();
    }
  }

  /**
   * Base directive link function
   *
   * @param   object  scope     Scope object used for evaluation
   * @param   object  iElement  Element to perform animation on
   * @param   object  iAttrs    reference to directive attributes
   * @param   string  collectionAttr Attribute name of element child selector
   *
   */
  function ngvLink(scope, iElement, iAttrs, collectionAttr, noToggle) {
    // Unwatchers
    var unwatch = null;
    // Flags
    var repeat = a.isDefined(iAttrs.ngvOnce) ? iAttrs.ngvOnce === 'false' : true,
        eager = a.isDefined(iAttrs.ngvEager) ? iAttrs.ngvEager !== 'false' : false,
        animated = false,
        collection = false;
    // Props
    var effect = 'fade';
    /* Attempt to evaluate ngvEffect if specified */
    if (iAttrs.ngvEffect) {
      effect = scope.$eval(iAttrs.ngvEffect);
      if (!effect) {
        effect = iAttrs.ngvEffect;
      }
    }
    /* Check if collectionAttr is valid */
    if (a.isDefined(collectionAttr) && !a.isDefined(iAttrs[collectionAttr])) {
      collectionAttr = 'ngvSelector';
    }
    collection = a.isDefined(iAttrs[collectionAttr]);

    if (!noToggle && iAttrs.ngvToggle && effect) {
      scope.$watch(iAttrs.ngvToggle, function(n, o) {
        var element = collection ? getNgvCollection(iElement, iAttrs[collectionAttr]) : iElement;
        var options = getNgvOptions(scope, iAttrs, n);
        if (!eager && n === o) {
          if (n) {
            element.css({display: options.display || 'inherited', opacity: 1});
          } else {
            element.css({display: options.display || 'none', opacity: 0});
          }
        } else {
          v(element, 'stop');
          if (a.isString(effect)) {
            v(element, effect+(n ? 'In' : 'Out'), options);
          } else {
            if (animated) {
              v(element, 'reverse', options);
            } else {
              v(element, effect, options);
              animated = true;
            }
          }
        }
      });
    } else if (iAttrs.ngvAnimate && effect) {
      unwatch = scope.$watch(iAttrs.ngvAnimate, function (n) {
        if (n) {
          var element = collection ? getNgvCollection(iElement, iAttrs[collectionAttr]) : iElement;
          var options = getNgvOptions(scope, iAttrs);
          v(element, effect, options);
          if (!repeat) {
            unwatch();
          }
        }
      });
    } else if (iAttrs.ngvTrigger && effect) {
      unwatch = scope.$on(iAttrs.ngvTrigger, function () {
        var element = collection ? getNgvCollection(iElement, iAttrs[collectionAttr]) : iElement;
        var options = getNgvOptions(scope, iAttrs);
        v(element, effect, options);
        if (!repeat) {
          unwatch();
        }
      });
    }
  }

  /**
   * Angulocity Module
   *
   * @ngmodule Angulocity
   */
  a.module('Angulocity', [])
  .provider('$ngvAnimator', function ngvAnimatorProvider() {
    var sequences = [];
    var defaults = {

    };

    this.defaults = defaults;
    this.RegisterEffect = a.isDefined(v.RegisterEffect) ? v.RegisterEffect : a.noop;
    this.RegisterSequence = function(name, sequence) {
      if (name && a.isObject(sequence)) {
        sequence[getNgvClass] = sequence;
      }
    };
    this.$get = ['$document', function ($document) {
      return {
        Velocity: v,
        animate: function (klass, effect, options) {
          var collection = getNgvCollection($document, klass);
          if (collection) {
            return v(collection, effect, options);
          }
        },
        element: function (klass) {
          return getNgvCollection($document, klass);
        },
        animateSequence: function(arg) {
          var seq, iSeq;
          if (a.isString(arg)) {
            seq = sequences[getNgvClass(name)];
            iSeq = [];
            for (var i = 0 ; i < seq.length; i++) {
              // Generate correct sequence format
              iSeq.push({e: getNgvCollection($document, seq[i].class), p: seq[i].properties, o: seq[i].options});
            }
            return v.RunSequence(iSeq);
          } else if (a.isObject(arg)) {
            return v.RunSequence(arg);
          }
        }
      };
    }];
  })
  /**
   * @ngdoc directive
   * @name  ngvSlide
   *
   */
  .directive('ngvSlide', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = a.isDefined(iAttrs.ngvOnce) ? iAttrs.ngvOnce === 'false' : false;
        var options;

        // If animation switch provided
        if (iAttrs.ngvSlide) {
          scope.$watch(iAttrs.ngvSlide, function(n, o) {
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                iElement.css({display: options.display || 'inherited'});
              } else {
                iElement.css({display: options.display || 'none'});
              }
            } else {
              if (n) {
                v(iElement, 'stop');
                v(iElement, 'slideDown', options);
              } else {
                v(iElement, 'stop');
                v(iElement, 'slideUp', options);
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(iElement, 'slideDown', options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(iElement, 'slideUp', options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvFade
   *
   */
  .directive('ngvFade', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        // Unwatchers
        var ngvIn = null,
            ngvOut = null;
        var repeat = a.isDefined(iAttrs.ngvOnce) ? iAttrs.ngvOnce === 'false' : false;
        var options;

        // If animation switch provided
        if (iAttrs.ngvFade) {
          scope.$watch(iAttrs.ngvFade, function(n, o) {
            options = getNgvOptions(scope, iAttrs, n);
            if (n === o) {
              if (n) {
                iElement.css({display: options.display || 'inherited', opacity: 1});
              } else {
                iElement.css({display: options.display || 'none', opacity: 0});
              }
            } else {
              if (n) {
                v(iElement, 'stop');
                v(iElement, 'fadeIn', options);
              } else {
                v(iElement, 'stop');
                v(iElement, 'fadeOut', options);
              }
            }
          });
        } else {
          options = getNgvOptions(scope, iAttrs, true);
          if (iAttrs.ngvIn) {
            ngvIn = scope.$watch(iAttrs.ngvIn, function (n) {
              if (n) {
                v(iElement, 'fadeIn', options);
                if (!repeat) {
                  ngvIn();
                }
              }
            });
          }
          options = getNgvOptions(scope, iAttrs, false);
          if (iAttrs.ngvOut) {
            ngvOut = scope.$watch(iAttrs.ngvOut, function(n) {
              if (n) {
                v(iElement, 'fadeOut', options);
                if (!repeat) {
                  ngvOut();
                }
              }
            });
          }
        }
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvClass
   *
   */
  .directive('ngvClass', [function () {
    return {
      restrict      : 'A',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        iElement.addClass(getNgvClass(iAttrs.ngvClass));
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvAnimator
   *
   */
  .directive('ngvAnimator', ['$document', function ($document) {
    return {
      restrict      : 'EA',
      scope         :  true,
      link          : function (scope, iElement, iAttrs) {
        var element = a.isDefined(iAttrs.ngvGlobal) ? $document : iElement.parent();
        ngvLink(scope, element, iAttrs, 'ngvSelect', true);
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvCollection
   *
   */
  .directive('ngvCollection', [function () {
    return {
      restrict      : 'EA',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        ngvLink(scope, iElement, iAttrs, 'ngvCollection');
      }
    };
  }])
  /**
   * @ngdoc directive
   * @name  ngvElement
   *
   */
  .directive('ngvElement', [function () {
    return {
      restrict      : 'EA',
      scope         :  false,
      link          : function (scope, iElement, iAttrs) {
        if (iAttrs.ngvElement) {
          iElement.addClass(getNgvClass(iAttrs.ngvElement));
        }
        ngvLink(scope, iElement, iAttrs);
      }
    };
  }])
  ;
})(window, void 0);
<|endoftext|>