<commit_before>import gatherInput from './gatherInput'
import {bootstrapSanity, bootstrapPlugin} from './bootstrap'
import {install as npmInstall} from '../../npm-bridge/install'
import getProjectDefaults from '../../util/getProjectDefaults'
import addPluginToManifest from '../../util/addPluginToManifest'

export default {
  name: 'init',
  signature: 'init [plugin]',
  description: 'Initialize a new Sanity project',
  action: (args, opts) => {
    const type = args.options._[1]
    if (!type) {
      return initSanity(args)
    }

    if (type === 'plugin') {
      return initPlugin(args)
    }

    // Do not use this, unless you're really sure you know what you're doing
    if (type === 'blåbær') {
      return initPlugin(args, {sanityStyle: true})
    }

    const error = new Error(`Unknown init type "${type}"`)
    args.error(error)
    return Promise.reject(error)
  }
}

function initSanity({print, prompt, spinner, error, options}) {
  print('This utility will walk you through creating a new Sanity installation.')
  print('It only covers the basic configuration, and tries to guess sensible defaults.\n')
  print('Press ^C at any time to quit.')

  const spin = spinner('Installing dependencies...')

  return getProjectDefaults(options.rootDir, options)
    .then(defaults => gatherInput(prompt, defaults))
    .then(answers => bootstrapSanity(options.rootDir, answers, print))
    .then(() => spin.start())
    .then(() => npmInstall())
    .then(() => spin.stop())
    .then(() => print('Success! You can now run `sanity start`'))
    .catch(err => {
      spin.stop()
      error(err)
    })
}

function initPlugin({print, prompt, error, options}, initOpts = {}) {
  if (initOpts.sanityStyle) {
    print('[WARNING]: Bootstrapping with Sanity.io style guide')
  }

  print('This utility will walk you through creating a new Sanity plugin.')
  print('It only covers the basic configuration, and tries to guess sensible defaults.\n')
  print('Press ^C at any time to quit.')

  const rootDir = options.rootDir
  return getProjectDefaults(rootDir, {isPlugin: true})
    .then(defaults => gatherInput(prompt, defaults, {isPlugin: true}))
    .then(answers => warnOnNonStandardPluginName(answers, print))
    .then(answers => bootstrapPlugin(answers, {print, ...initOpts}))
    .then(answers => addPluginOnUserConfirm(rootDir, answers))
    .then(answers => print(`Success! Plugin initialized at ${answers.outputPath}`))
    .catch(error)
}

function addPluginOnUserConfirm(rootDir, answers) {
  if (!answers.addPluginToManifest) {
    return answers
  }

  return addPluginToManifest(
    rootDir,
    answers.name.replace(/^sanity-plugin-/, '')
  ).then(() => answers)
}

function warnOnNonStandardPluginName(answers, print) {
  if (answers.name.indexOf('sanity-plugin-') !== 0) {
    print([
      '[Warning] If you intend to publish the plugin for reuse by others, ',
      'it is recommended that the plugin name is prefixed with `sanity-plugin-`'
    ].join(''))
  }

  return answers
}
<commit_msg>Move note about naming conventions to the start of the command<commit_after>import gatherInput from './gatherInput'
import {bootstrapSanity, bootstrapPlugin} from './bootstrap'
import {install as npmInstall} from '../../npm-bridge/install'
import getProjectDefaults from '../../util/getProjectDefaults'
import addPluginToManifest from '../../util/addPluginToManifest'

export default {
  name: 'init',
  signature: 'init [plugin]',
  description: 'Initialize a new Sanity project',
  action: (args, opts) => {
    const type = args.options._[1]

    if (!type) {
      return initSanity(args)
    }

    if (type === 'plugin') {
      return initPlugin(args)
    }

    // Do not use this, unless you're really sure you know what you're doing
    if (type === 'blåbær') {
      return initPlugin(args, {sanityStyle: true})
    }

    const error = new Error(`Unknown init type "${type}"`)
    args.error(error)
    return Promise.reject(error)
  }
}

function initSanity({print, prompt, spinner, error, options}) {
  print('This utility will walk you through creating a new Sanity installation.')
  print('It only covers the basic configuration, and tries to guess sensible defaults.\n')
  print('Press ^C at any time to quit.')

  const spin = spinner('Installing dependencies...')

  return getProjectDefaults(options.rootDir, options)
    .then(defaults => gatherInput(prompt, defaults))
    .then(answers => bootstrapSanity(options.rootDir, answers, print))
    .then(() => spin.start())
    .then(() => npmInstall())
    .then(() => spin.stop())
    .then(() => print('Success! You can now run `sanity start`'))
    .catch(err => {
      spin.stop()
      error(err)
    })
}

function initPlugin({print, prompt, error, options}, initOpts = {}) {
  if (initOpts.sanityStyle) {
    print('[WARNING]: Bootstrapping with Sanity.io style guide')
  }

  print('This utility will walk you through creating a new Sanity plugin.')
  print('It only covers the basic configuration, and tries to guess sensible defaults.\n')
  print('Press ^C at any time to quit.\n')

  print(
    'If you intend to publish the plugin for reuse by others, it is '
    + 'recommended that the plugin name is prefixed with `sanity-plugin-`'
  )

  const rootDir = options.rootDir
  return getProjectDefaults(rootDir, {isPlugin: true})
    .then(defaults => gatherInput(prompt, defaults, {isPlugin: true}))
    .then(answers => bootstrapPlugin(answers, {print, ...initOpts}))
    .then(answers => addPluginOnUserConfirm(rootDir, answers))
    .then(answers => print(`Success! Plugin initialized at ${answers.outputPath}`))
    .catch(error)
}

function addPluginOnUserConfirm(rootDir, answers) {
  if (!answers.addPluginToManifest) {
    return answers
  }

  return addPluginToManifest(
    rootDir,
    answers.name.replace(/^sanity-plugin-/, '')
  ).then(() => answers)
}
<|endoftext|>


<commit_before>'use strict';

(function(app) {

  /**
   * Defines the device controller for displaying details
   */
  function DeviceController(
    $scope,
    $filter,
    $timeout,
    $window,
    $location,
    manageService,
    entityService,
    manageName) {

    var self = this,
      openedDevice = null,
      activePage = 0;

    // Available state for device
    self.STATE_ACCEPTED = 'accepted';
    self.STATE_PENDING = 'pending';
    self.STATE_REFUSED = 'refused';

    /**
     * Define an ui-state for a device
     *
     * @param target The target device or group
     * @param {String} uiState The ui-state to set for the device
     */
    function setUiState(target, uiState) {
      var element = (angular.element(target).scope().device) ?
        angular.element(target).scope().device : angular.element(target).scope().group;

      if (!element['ui-state']) {
        element['ui-state'] = [];
      }
      element['ui-state'].push(uiState);
      $scope.$apply();
    }

    /**
     * Remove an ui-state for a device
     *
     * @param target The target device or group
     * @param {String} uiState The ui-state to remove for the device
     */
    function removeUiState(target, uiState) {
      var element = (angular.element(target).scope().device) ?
        angular.element(target).scope().device : angular.element(target).scope().group;
      var index = element['ui-state'].indexOf(uiState);

      element['ui-state'].splice(index, 1);
      $scope.$apply();
    }

    /**
     * Move element on drag
     * @param {Object} event the user Event related to the dragEvent
     */
    function dragMoveListener(event) {
      var element = angular.element(event.target),
        x = (parseFloat(element.attr('data-x')) || 0) + event.dx,
        y = (parseFloat(element.attr('data-y')) || 0) + event.dy;

      // translate the element
      element.css({
        '-webkit-transform': 'translate(' + x + 'px, ' + y + 'px)',
        transform: 'translate(' + x + 'px, ' + y + 'px)'
      });

      // update the position attributes
      element.attr('data-x', x);
      element.attr('data-y', y);
    }

    /**
     * Reset the device element to its initial position
     * @param {Object} target the element to reset position
     */
    function resetPosition(target) {
      var element = angular.element(target);

      // Set transition duration for reset
      element.css({
        '-webkit-transition-duration': '.5s',
        'transition-duration': '.5s',
        '-webkit-transform': 'translate(0, 0)',
        transform: 'translate(0, 0)'
      });
      element.parent().css({
        'z-index': 2
      });

      // update the position attributes
      element.attr('data-x', 0);
      element.attr('data-y', 0);
    }

    /**
     * Set position of the target element to the dropzone element
     *
     * @param target
     * @param relatedTarget
     */
    function mergePosition(target, relatedTarget) {
      var x = parseInt(target.getBoundingClientRect().left) -
          (relatedTarget.parentNode.getBoundingClientRect().left + 15),
        y = parseInt(target.getBoundingClientRect().top - relatedTarget.parentNode.getBoundingClientRect().top),
        element = angular.element(relatedTarget);

      element.css({
        '-webkit-transition-duration': '.75s',
        'transition-duration': '.75s',
        '-webkit-transform': 'translate(' + x + 'px, ' + y + 'px)',
        transform: 'translate(' + x + 'px, ' + y + 'px)'
      });

      removeUiState(target, 'can-drop');
    }

    /**
     * Manage the dragging event
     */
    function draggable() {
      /* global interact */
      interact('.draggable').draggable({
        inertia: false,

        // Define the restricted area
        restrict: {
          restriction: '#page-content-wrapper',
          endOnly: true
        },
        autoScroll: true,

        onstart: function(event) {
          var element = angular.element(event.target);

          setUiState(event.target, 'drag');

          // Set transition duration for reset
          element.css({
            '-webkit-transition-duration': '0s',
            'transition-duration': '0s'
          });
          element.parent().css({
            'z-index': 1
          });
        },

        onmove: dragMoveListener,

        onend: function(event) {
          var target = event.target;

          if (!angular.element(target).hasClass('drop-target')) {
            removeUiState(target, 'drag');
            resetPosition(target);
          }
        }
      });
    }

    /**
     * Add devices to a group, group is created if does not exist
     *
     * @param draggableId
     * @param dropzoneId
     * @param isGroup
     */
    function addDeviceToGroup(draggableId, dropzoneId, isGroup) {

      // Create the group if it's two devices
      if (!isGroup) {
        var group;

        entityService.addEntity('groups', manageName, {}).then(function(result) {
          group = result.data.entity;
          entityService.updateEntity('devices', manageName, draggableId, {group: group.id}).then(function() {});
          entityService.updateEntity('devices', manageName, dropzoneId, {group: group.id}).then(function() {});
          manageService.addDevicesToGroup(draggableId, dropzoneId, group).then(function() {});

          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        }, function() {
          $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
        });
      } else {
        entityService.updateEntity('devices', manageName, draggableId, {group: dropzoneId}).then(function() {
          manageService.addDevicesToGroup(draggableId, dropzoneId).then(function() {});

          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        }, function() {
          $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
        });
      }
    }

    /**
     * Allow to drop element in dropzones
     */
    function dragDropDevice() {
      interact('.dropzone').dropzone({

        // only accept elements matching this CSS selector
        accept: '.draggable',

        // Require a 25% element overlap for a drop to be possible
        overlap: 0.25,

        ondragenter: function(event) {
          setUiState(event.target, 'can-drop');
          setUiState(event.relatedTarget, 'drop-target');
        },
        ondragleave: function(event) {
          removeUiState(event.relatedTarget, 'drop-target');
          removeUiState(event.target, 'can-drop');
        },
        ondrop: function(event) {
          var relatedTarget = angular.element(event.relatedTarget),
            target = angular.element(event.target);

          mergePosition(event.target, event.relatedTarget);
          $timeout(function() {
            addDeviceToGroup(relatedTarget.attr('data-id'),
              target.attr('data-id'), target.hasClass('group'));
          }, 500);
        }
      });
    }

    /**
     * Permits to organize the view when the details is opened/closed
     *
     * @param opening
     */
    function organizeLayout(opening) {

      var screenWidth = $window.innerWidth,
        containerWidth = parseInt(document.getElementsByClassName('manage-container')[0].offsetWidth + 30),
        leftSpace = parseInt(screenWidth - containerWidth) / 2;

      if (opening && leftSpace <= 300) {
        if (containerWidth <= 750) {
          $scope.manage.resize = 'small';
        } else {
          $scope.manage.resize = 'medium';
        }
      } else {
        $scope.manage.resize = 'normal';
      }
    }

    /**
     * Display the device/group detail on tile click
     */
    function clickDevice() {

      // Avoid to fired the same event multiple times
      var events = interact('.device > .well, .device-group > .group')._iEvents;
      if (Object.keys(events).length && events.tap) {
        delete events.tap;
      }

      interact('.device > .well, .device-group > .group').on('tap', function(event) {
        if (event.double) {
          return;
        }

        var deviceId = event.currentTarget.getAttribute('data-id');

        if (!openedDevice) {
          openedDevice = deviceId;
          $scope.manage.deviceSelected = true;
          setUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
          // deviceService.getDetails(deviceId);
        } else if (openedDevice == deviceId) {
          openedDevice = null;
          $scope.manage.deviceSelected = false;
          removeUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
        } else {
          openedDevice = deviceId;

          // removeUiState(deviceService.getTarget(), 'selected');
          $scope.clearUiState('selected');
          setUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
          // deviceService.getDetails(deviceId);
        }

        organizeLayout($scope.manage.deviceSelected);
        $scope.$apply();
      });
    }

    /**
     * Go to the group detail page on double click
     */
    function dbClickGroupDevices() {

      // Avoid to fired the same event multiple times
      var events = interact('.device-group > .group')._iEvents;
      if (Object.keys(events).length && events.doubletap) {
        delete events.doubletap;
      }

      interact('.device-group > .group').on('doubletap', function(event) {
        var groupId = event.currentTarget.getAttribute('data-id');

        $scope.manage.deviceSelected = false;
        $scope.clearUiState('selected');
        $location.path('manage/group-detail/' + groupId);
        $scope.manage.absUrl = $location.absUrl();
        $scope.$apply();
      });
    }

    /**
     * Add pending/refused device to the accepted list of devices
     *
     * @param device
     * @param state
     */
    self.addToAcceptedDevices = function(device, state) {
      var deviceToSave = {state: self.STATE_ACCEPTED};

      entityService.updateEntity('devices', manageName, device.id, deviceToSave).then(function() {

        // Ask for device detail
        $scope.socket.emit('device-detail', device.id);
        manageService.updateDeviceState(device, state, true).then(function() {
          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        });
      }, function() {
        $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
      });
    };

    /**
     * Add the new device to the refused list of devices
     *
     * @param device
     * @param state
     */
    self.addToRefusedDevices = function(device, state) {
      device.state = self.STATE_REFUSED;

      entityService.updateEntity('devices', manageName, device.id, device).then(function() {
        manageService.updateDeviceState(device, state, false).then(function() {
          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        });
      }, function() {
        $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
      });
    };

    /**
     * Define the active page index
     *
     * @param index
     */
    self.setActivePage = function(index) {
      activePage = index;
    };

    /**
     * Determine if the passed index is the active page index
     *
     * @param index
     * @returns {boolean}
     */
    self.isActivePage = function(index) {
      return activePage === index;
    };

    // Manage drag and drop events
    draggable();
    dragDropDevice();

    // Manage click events
    clickDevice();
    dbClickGroupDevices();

  }

  app.controller('DeviceController', DeviceController);
  DeviceController.$inject = [
    '$scope',
    '$filter',
    '$timeout',
    '$window',
    '$location',
    'manageService',
    'entityService',
    'manageName'
  ];

})(angular.module('ov.manage'));
<commit_msg>Add function to remove the device connected on first connection after an user response<commit_after>'use strict';

(function(app) {

  /**
   * Defines the device controller for displaying details
   */
  function DeviceController(
    $scope,
    $filter,
    $timeout,
    $window,
    $location,
    manageService,
    entityService,
    manageName) {

    var self = this,
      openedDevice = null,
      activePage = 0;

    // Available state for device
    self.STATE_ACCEPTED = 'accepted';
    self.STATE_PENDING = 'pending';
    self.STATE_REFUSED = 'refused';

    /**
     * Define an ui-state for a device
     *
     * @param target The target device or group
     * @param {String} uiState The ui-state to set for the device
     */
    function setUiState(target, uiState) {
      var element = (angular.element(target).scope().device) ?
        angular.element(target).scope().device : angular.element(target).scope().group;

      if (!element['ui-state']) {
        element['ui-state'] = [];
      }
      element['ui-state'].push(uiState);
      $scope.$apply();
    }

    /**
     * Remove an ui-state for a device
     *
     * @param target The target device or group
     * @param {String} uiState The ui-state to remove for the device
     */
    function removeUiState(target, uiState) {
      var element = (angular.element(target).scope().device) ?
        angular.element(target).scope().device : angular.element(target).scope().group;
      var index = element['ui-state'].indexOf(uiState);

      element['ui-state'].splice(index, 1);
      $scope.$apply();
    }

    /**
     * Move element on drag
     * @param {Object} event the user Event related to the dragEvent
     */
    function dragMoveListener(event) {
      var element = angular.element(event.target),
        x = (parseFloat(element.attr('data-x')) || 0) + event.dx,
        y = (parseFloat(element.attr('data-y')) || 0) + event.dy;

      // translate the element
      element.css({
        '-webkit-transform': 'translate(' + x + 'px, ' + y + 'px)',
        transform: 'translate(' + x + 'px, ' + y + 'px)'
      });

      // update the position attributes
      element.attr('data-x', x);
      element.attr('data-y', y);
    }

    /**
     * Reset the device element to its initial position
     * @param {Object} target the element to reset position
     */
    function resetPosition(target) {
      var element = angular.element(target);

      // Set transition duration for reset
      element.css({
        '-webkit-transition-duration': '.5s',
        'transition-duration': '.5s',
        '-webkit-transform': 'translate(0, 0)',
        transform: 'translate(0, 0)'
      });
      element.parent().css({
        'z-index': 2
      });

      // update the position attributes
      element.attr('data-x', 0);
      element.attr('data-y', 0);
    }

    /**
     * Set position of the target element to the dropzone element
     *
     * @param target
     * @param relatedTarget
     */
    function mergePosition(target, relatedTarget) {
      var x = parseInt(target.getBoundingClientRect().left) -
          (relatedTarget.parentNode.getBoundingClientRect().left + 15),
        y = parseInt(target.getBoundingClientRect().top - relatedTarget.parentNode.getBoundingClientRect().top),
        element = angular.element(relatedTarget);

      element.css({
        '-webkit-transition-duration': '.75s',
        'transition-duration': '.75s',
        '-webkit-transform': 'translate(' + x + 'px, ' + y + 'px)',
        transform: 'translate(' + x + 'px, ' + y + 'px)'
      });

      removeUiState(target, 'can-drop');
    }

    /**
     * Manage the dragging event
     */
    function draggable() {
      /* global interact */
      interact('.draggable').draggable({
        inertia: false,

        // Define the restricted area
        restrict: {
          restriction: '#page-content-wrapper',
          endOnly: true
        },
        autoScroll: true,

        onstart: function(event) {
          var element = angular.element(event.target);

          setUiState(event.target, 'drag');

          // Set transition duration for reset
          element.css({
            '-webkit-transition-duration': '0s',
            'transition-duration': '0s'
          });
          element.parent().css({
            'z-index': 1
          });
        },

        onmove: dragMoveListener,

        onend: function(event) {
          var target = event.target;

          if (!angular.element(target).hasClass('drop-target')) {
            removeUiState(target, 'drag');
            resetPosition(target);
          }
        }
      });
    }

    /**
     * Add devices to a group, group is created if does not exist
     *
     * @param draggableId
     * @param dropzoneId
     * @param isGroup
     */
    function addDeviceToGroup(draggableId, dropzoneId, isGroup) {

      // Create the group if it's two devices
      if (!isGroup) {
        var group;

        entityService.addEntity('groups', manageName, {}).then(function(result) {
          group = result.data.entity;
          entityService.updateEntity('devices', manageName, draggableId, {group: group.id}).then(function() {});
          entityService.updateEntity('devices', manageName, dropzoneId, {group: group.id}).then(function() {});
          manageService.addDevicesToGroup(draggableId, dropzoneId, group).then(function() {});

          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        }, function() {
          $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
        });
      } else {
        entityService.updateEntity('devices', manageName, draggableId, {group: dropzoneId}).then(function() {
          manageService.addDevicesToGroup(draggableId, dropzoneId).then(function() {});

          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        }, function() {
          $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
        });
      }
    }

    /**
     * Allow to drop element in dropzones
     */
    function dragDropDevice() {
      interact('.dropzone').dropzone({

        // only accept elements matching this CSS selector
        accept: '.draggable',

        // Require a 25% element overlap for a drop to be possible
        overlap: 0.25,

        ondragenter: function(event) {
          setUiState(event.target, 'can-drop');
          setUiState(event.relatedTarget, 'drop-target');
        },
        ondragleave: function(event) {
          removeUiState(event.relatedTarget, 'drop-target');
          removeUiState(event.target, 'can-drop');
        },
        ondrop: function(event) {
          var relatedTarget = angular.element(event.relatedTarget),
            target = angular.element(event.target);

          mergePosition(event.target, event.relatedTarget);
          $timeout(function() {
            addDeviceToGroup(relatedTarget.attr('data-id'),
              target.attr('data-id'), target.hasClass('group'));
          }, 500);
        }
      });
    }

    /**
     * Permits to organize the view when the details is opened/closed
     *
     * @param opening
     */
    function organizeLayout(opening) {

      var screenWidth = $window.innerWidth,
        containerWidth = parseInt(document.getElementsByClassName('manage-container')[0].offsetWidth + 30),
        leftSpace = parseInt(screenWidth - containerWidth) / 2;

      if (opening && leftSpace <= 300) {
        if (containerWidth <= 750) {
          $scope.manage.resize = 'small';
        } else {
          $scope.manage.resize = 'medium';
        }
      } else {
        $scope.manage.resize = 'normal';
      }
    }

    /**
     * Display the device/group detail on tile click
     */
    function clickDevice() {

      // Avoid to fired the same event multiple times
      var events = interact('.device > .well, .device-group > .group')._iEvents;
      if (Object.keys(events).length && events.tap) {
        delete events.tap;
      }

      interact('.device > .well, .device-group > .group').on('tap', function(event) {
        if (event.double) {
          return;
        }

        var deviceId = event.currentTarget.getAttribute('data-id');

        if (!openedDevice) {
          openedDevice = deviceId;
          $scope.manage.deviceSelected = true;
          setUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
          // deviceService.getDetails(deviceId);
        } else if (openedDevice == deviceId) {
          openedDevice = null;
          $scope.manage.deviceSelected = false;
          removeUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
        } else {
          openedDevice = deviceId;

          // removeUiState(deviceService.getTarget(), 'selected');
          $scope.clearUiState('selected');
          setUiState(event.currentTarget, 'selected');

          // deviceService.setTarget(event.currentTarget);
          // deviceService.getDetails(deviceId);
        }

        organizeLayout($scope.manage.deviceSelected);
        $scope.$apply();
      });
    }

    /**
     * Go to the group detail page on double click
     */
    function dbClickGroupDevices() {

      // Avoid to fired the same event multiple times
      var events = interact('.device-group > .group')._iEvents;
      if (Object.keys(events).length && events.doubletap) {
        delete events.doubletap;
      }

      interact('.device-group > .group').on('doubletap', function(event) {
        var groupId = event.currentTarget.getAttribute('data-id');

        $scope.manage.deviceSelected = false;
        $scope.clearUiState('selected');
        $location.path('manage/group-detail/' + groupId);
        $scope.manage.absUrl = $location.absUrl();
        $scope.$apply();
      });
    }

    /**
     * Remove a device from the device connexion object on user response
     *
     * @param {int} id The device id to remove
     */
    function removeDeviceConnected(id) {
      for (var i = 0; i < $scope.devicesConnexion.length; i++) {
        if ($scope.devicesConnexion[i].id == id) {
          $scope.devicesConnexion.splice(i, 1);
          break;
        }
      }
    }

    /**
     * Add pending/refused device to the accepted list of devices
     *
     * @param device
     * @param state
     */
    self.addToAcceptedDevices = function(device, state) {
      var deviceToSave = {state: self.STATE_ACCEPTED};

      entityService.updateEntity('devices', manageName, device.id, deviceToSave).then(function() {

        // Ask for device detail
        $scope.socket.emit('device-detail', device.id);
        removeDeviceConnected(device.id);
        manageService.updateDeviceState(device, state, true).then(function() {
          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        });
      }, function() {
        $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
      });
    };

    /**
     * Add the new device to the refused list of devices
     *
     * @param device
     * @param state
     */
    self.addToRefusedDevices = function(device, state) {
      device.state = self.STATE_REFUSED;

      entityService.updateEntity('devices', manageName, device.id, device).then(function() {
        removeDeviceConnected(device.id);
        manageService.updateDeviceState(device, state, false).then(function() {
          $scope.$emit('setAlert', 'success', $filter('translate')('MANAGE.DEVICE.SAVE_SUCCESS'), 4000);
        });
      }, function() {
        $scope.$emit('setAlert', 'danger', $filter('translate')('MANAGE.DEVICE.SAVE_ERROR'), 4000);
      });
    };

    /**
     * Define the active page index
     *
     * @param index
     */
    self.setActivePage = function(index) {
      activePage = index;
    };

    /**
     * Determine if the passed index is the active page index
     *
     * @param index
     * @returns {boolean}
     */
    self.isActivePage = function(index) {
      return activePage === index;
    };

    // Manage drag and drop events
    draggable();
    dragDropDevice();

    // Manage click events
    clickDevice();
    dbClickGroupDevices();

  }

  app.controller('DeviceController', DeviceController);
  DeviceController.$inject = [
    '$scope',
    '$filter',
    '$timeout',
    '$window',
    '$location',
    'manageService',
    'entityService',
    'manageName'
  ];

})(angular.module('ov.manage'));
<|endoftext|>


<commit_before>// Helper function to extract inner object from array
export function getSubArray(targetArray, objProperty, value) {
  var i,
    totalItems = targetArray.length,
    objFound = false,
    idxArr = [];

  console.log(objProperty);
  for (i = 0; i < totalItems; i++) {
    if (targetArray[i][objProperty] === value) {
      objFound = true;
      idxArr.push(targetArray[i]);
    }
  }
  return idxArr;
}
<commit_msg>chore: remove comment<commit_after>// Helper function to extract inner object from array
export function getSubArray(targetArray, objProperty, value) {
  var i,
    totalItems = targetArray.length,
    objFound = false,
    idxArr = [];

  for (i = 0; i < totalItems; i++) {
    if (targetArray[i][objProperty] === value) {
      objFound = true;
      idxArr.push(targetArray[i]);
    }
  }
  return idxArr;
}
<|endoftext|>


<commit_before>"use strict"

const containsString = require("../../utils/containsString")
const functionArgumentsSearch = require("../../utils/functionArgumentsSearch")
const isStandardSyntaxUrl = require("../../utils/isStandardSyntaxUrl")
const report = require("../../utils/report")
const ruleMessages = require("../../utils/ruleMessages")
const validateOptions = require("../../utils/validateOptions")
const _ = require("lodash")
const parse = require("url").parse

const ruleName = "function-url-scheme-whitelist"

const messages = ruleMessages(ruleName, {
  rejected: scheme => `Unexpected url scheme "${scheme}:"`,
})

const rule = function (whitelist) {
  return (root, result) => {
    const validOptions = validateOptions(result, ruleName, {
      actual: whitelist,
      possible: [_.isString],
    })
    if (!validOptions) {
      return
    }

    root.walkDecls(function (decl) {
      functionArgumentsSearch(decl.toString().toLowerCase(), "url", (args, index) => {
        const unspacedUrlString = _.trim(args, " ")
        if (!isStandardSyntaxUrl(unspacedUrlString)) {
          return
        }
        const urlString = _.trim(unspacedUrlString, "'\"")

        const url = parse(urlString)
        if (url.protocol === null) {
          return
        }

        const scheme = url.protocol.toLowerCase().slice(0, -1) // strip trailing `:`

        // The URL spec does not require a scheme to be followed by `//`, but checking
        // for it allows this rule to differentiate <scheme>:<hostname> urls from
        // <hostname>:<port> urls. `data:` scheme urls are an exception to this rule.
        const slashIndex = url.protocol.length
        const expectedSlashes = urlString.slice(slashIndex, slashIndex + 2)
        const isSchemeLessUrl = expectedSlashes !== "//" && scheme !== "data"
        if (isSchemeLessUrl) {
          return
        }

        const whitelistLowerCase = typeof whitelist === "string" ? whitelist.toLowerCase() : whitelist.join("|").toLowerCase().split("|")

        if (containsString(scheme, whitelistLowerCase)) {
          return
        }

        report({
          message: messages.rejected(scheme),
          node: decl,
          index,
          result,
          ruleName,
        })
      })
    })
  }
}

rule.ruleName = ruleName
rule.messages = messages
module.exports = rule
<commit_msg>Fix not specified array as primary option for "function-url-scheme-whitelist" (#2447)<commit_after>"use strict"

const containsString = require("../../utils/containsString")
const functionArgumentsSearch = require("../../utils/functionArgumentsSearch")
const isStandardSyntaxUrl = require("../../utils/isStandardSyntaxUrl")
const report = require("../../utils/report")
const ruleMessages = require("../../utils/ruleMessages")
const validateOptions = require("../../utils/validateOptions")
const _ = require("lodash")
const parse = require("url").parse

const ruleName = "function-url-scheme-whitelist"

const messages = ruleMessages(ruleName, {
  rejected: scheme => `Unexpected url scheme "${scheme}:"`,
})

const rule = function (whitelist) {
  return (root, result) => {
    const validOptions = validateOptions(result, ruleName, {
      actual: whitelist,
      possible: [_.isString],
    })
    if (!validOptions) {
      return
    }

    root.walkDecls(function (decl) {
      functionArgumentsSearch(decl.toString().toLowerCase(), "url", (args, index) => {
        const unspacedUrlString = _.trim(args, " ")
        if (!isStandardSyntaxUrl(unspacedUrlString)) {
          return
        }
        const urlString = _.trim(unspacedUrlString, "'\"")

        const url = parse(urlString)
        if (url.protocol === null) {
          return
        }

        const scheme = url.protocol.toLowerCase().slice(0, -1) // strip trailing `:`

        // The URL spec does not require a scheme to be followed by `//`, but checking
        // for it allows this rule to differentiate <scheme>:<hostname> urls from
        // <hostname>:<port> urls. `data:` scheme urls are an exception to this rule.
        const slashIndex = url.protocol.length
        const expectedSlashes = urlString.slice(slashIndex, slashIndex + 2)
        const isSchemeLessUrl = expectedSlashes !== "//" && scheme !== "data"
        if (isSchemeLessUrl) {
          return
        }

        const whitelistLowerCase = typeof whitelist === "string" ? whitelist.toLowerCase() : whitelist.join("|").toLowerCase().split("|")

        if (containsString(scheme, whitelistLowerCase)) {
          return
        }

        report({
          message: messages.rejected(scheme),
          node: decl,
          index,
          result,
          ruleName,
        })
      })
    })
  }
}

rule.primaryOptionArray = true

rule.ruleName = ruleName
rule.messages = messages
module.exports = rule
<|endoftext|>


<commit_before>/**
 * @property Bootstrap.ButtonDropdown
 * @type {Ember.View}
 */
Bootstrap.ButtonDropdown = Ember.View.extend({

    /**
     * @property label
     * @type {String}
     */
    label: null,

    /**
     * @property items
     * @type {Array}
     */
    items: [],

    /**
     * @property classNames
     * @type {Array}
     */
    classNames: ['btn-group'],

    /**
     * @property layout
     * @type {Function}
     */
    layout: Ember.Handlebars.compile('{{view.label}}' +
                                     '
{{yield}}
'),

    /**
     * @property template
     * @type {Function}
     */
    template: Ember.Handlebars.compile('{{#if view.items}} {{#each item in view.items}}' +
                                       '
{{view view.Item contextBinding="item"}}
' +
                                       '{{/each}} {{/if}}'),

    /**
     * @method didInsertElement
     * @return {void}
     */
    didInsertElement: function() {

        var items   = Ember.get(this, 'items'),
            forEach = Ember.EnumerableUtils.forEach;

        forEach(items, function(item) {

            // Iterate over the items, and if the `disabled` property changes, notify the
            // view of an update.
            Ember.addObserver(item, 'disabled', function() {
                this.notifyPropertyChange('view.items');
            });

        }, this);

    },

    /**
     * @property Item
     * @type {Ember.View}
     */
    Item: Ember.View.extend({

        /**
         * @property tagName
         * @type {String}
         * @default "a"
         */
        tagName: 'a',

        /**
         * @attributeBindings
         * @type {Array}
         */
        attributeBindings: ['href'],

        /**
         * @property template
         * @type {Function}
         */
        template: Ember.Handlebars.compile('{{label}}'),

        /**
         * @property href
         * @type {Object}
         * @return {String}
         */
        href: Ember.computed(function() {
            return 'javascript:void(0);';
        }),

        /**
         * @method click
         * Attempt to invoke the specified action name on the controller.
         * @return {void}
         */
        click: function() {

            var item        = Ember.get(this, 'context'),
                actionName  = Ember.get(item, 'actionName'),
                controller  = Ember.get(this, 'controller');

            if (Ember.get(item, 'disabled') === true) {
                // We won't invoke the action if it's disabled.
                return;
            }

            Ember.assert('View `Bootstrap.ButtonDropdown` does not have a controller attached.', !!Ember.get(this, 'controller'));
            Ember.assert('Controller `%@` does not have an action `%@`!'.fmt(controller, actionName), !!Ember.canInvoke(controller, actionName));

            // Invoke the action on the controller, passing in the item as the first param.
            Ember.tryInvoke(controller, actionName, item);

        }

    })

});<commit_msg>Small correction in the YUIDoc comment<commit_after>/**
 * @property Bootstrap.ButtonDropdown
 * @type {Ember.View}
 */
Bootstrap.ButtonDropdown = Ember.View.extend({

    /**
     * @property label
     * @type {String}
     */
    label: null,

    /**
     * @property items
     * @type {Array}
     */
    items: [],

    /**
     * @property classNames
     * @type {Array}
     */
    classNames: ['btn-group'],

    /**
     * @property layout
     * @type {Function}
     */
    layout: Ember.Handlebars.compile('{{view.label}}' +
                                     '
{{yield}}
'),

    /**
     * @property template
     * @type {Function}
     */
    template: Ember.Handlebars.compile('{{#if view.items}} {{#each item in view.items}}' +
                                       '
{{view view.Item contextBinding="item"}}
' +
                                       '{{/each}} {{/if}}'),

    /**
     * @method didInsertElement
     * @return {void}
     */
    didInsertElement: function() {

        var items   = Ember.get(this, 'items'),
            forEach = Ember.EnumerableUtils.forEach;

        forEach(items, function(item) {

            // Iterate over the items, and if the `disabled` property changes, notify the
            // view of an update.
            Ember.addObserver(item, 'disabled', function() {
                this.notifyPropertyChange('view.items');
            });

        }, this);

    },

    /**
     * @property Item
     * @type {Ember.View}
     */
    Item: Ember.View.extend({

        /**
         * @property tagName
         * @type {String}
         * @default "a"
         */
        tagName: 'a',

        /**
         * @property attributeBindings
         * @type {Array}
         */
        attributeBindings: ['href'],

        /**
         * @property template
         * @type {Function}
         */
        template: Ember.Handlebars.compile('{{label}}'),

        /**
         * @property href
         * @type {Object}
         * @return {String}
         */
        href: Ember.computed(function() {
            return 'javascript:void(0);';
        }),

        /**
         * @method click
         * Attempt to invoke the specified action name on the controller.
         * @return {void}
         */
        click: function() {

            var item        = Ember.get(this, 'context'),
                actionName  = Ember.get(item, 'actionName'),
                controller  = Ember.get(this, 'controller');

            if (Ember.get(item, 'disabled') === true) {
                // We won't invoke the action if it's disabled.
                return;
            }

            Ember.assert('View `Bootstrap.ButtonDropdown` does not have a controller attached.', !!Ember.get(this, 'controller'));
            Ember.assert('Controller `%@` does not have an action `%@`!'.fmt(controller, actionName), !!Ember.canInvoke(controller, actionName));

            // Invoke the action on the controller, passing in the item as the first param.
            Ember.tryInvoke(controller, actionName, item);

        }

    })

});<|endoftext|>


<commit_before>//transfer.js
import _ from '../../utils/util.js';
import API from '../../services/api';

const App = getApp();

Page({
  data: {
    wallet: '',
    money: '',
    remark: ''
  },
  onLoad: function (options) {
    const that = this;
    const id = options.id;
    if (id) {
      that.setData({
        wallet: id
      });
    }
  },
  handleScan: function () {
    const that = this;
    wx.scanCode({
      onlyFromCamera: false,
      success: function (res) {
        console.log('res: ', JSON.stringify(res, null, 2));
        that.setData({
          wallet: res.result || 'zWw594f57535a553Z2r'
        });
      },
      fail: function (res) {
        console.error('res: ', JSON.stringify(res, null, 2));
        that.setData({
          wallet: 'zWw594f57535a553Z2r'
        });
      }
    });
  },
  formSubmit: function (e) {
    const that = this;
    console.log('form发生了submit事件，携带数据为：', e.detail.value);
    API.handleWalletTransfer(e.detail.value).then(json => {
      if (json && json.code === 0) {
        console.log('transferInfo: ', JSON.stringify(json, null, 2));
        _.showToast('转账成功', 2000, 'success', function() {
          wx.navigateBack({
            delta: 1
          });
        });
      } else {
        if (json.code === 2005) {
          _.errorTips();
          return;
        }
        _.showToast(json.msg, 2000, 'loading');
      }
    }, err => {
      _.showToast(err.msg, 2000, 'loading');
    });
  },
  formReset: function () {
    console.log('form发生了reset事件')
  }
})
<commit_msg>收款钱包地址置空。<commit_after>//transfer.js
import _ from '../../utils/util.js';
import API from '../../services/api';

const App = getApp();

Page({
  data: {
    wallet: '',
    money: '',
    remark: ''
  },
  onLoad: function (options) {
    const that = this;
    const id = options.id;
    if (id) {
      that.setData({
        wallet: id
      });
    }
  },
  handleScan: function () {
    const that = this;
    wx.scanCode({
      onlyFromCamera: false,
      success: function (res) {
        console.log('res: ', JSON.stringify(res, null, 2));
        that.setData({
          wallet: res.result || ''
        });
      },
      fail: function (res) {
        console.error('res: ', JSON.stringify(res, null, 2));
        that.setData({
          wallet: ''
        });
      }
    });
  },
  formSubmit: function (e) {
    const that = this;
    console.log('form发生了submit事件，携带数据为：', e.detail.value);
    API.handleWalletTransfer(e.detail.value).then(json => {
      if (json && json.code === 0) {
        console.log('transferInfo: ', JSON.stringify(json, null, 2));
        _.showToast('转账成功', 2000, 'success', function() {
          wx.navigateBack({
            delta: 1
          });
        });
      } else {
        if (json.code === 2005) {
          _.errorTips();
          return;
        }
        _.showToast(json.msg, 2000, 'loading');
      }
    }, err => {
      _.showToast(err.msg, 2000, 'loading');
    });
  },
  formReset: function () {
    console.log('form发生了reset事件')
  }
})
<|endoftext|>


<commit_before>browser.on("init", function () {
    "use strict";

    const LOC_CACHE = new Map;
    const URI = Windows.Foundation.Uri;
    const RE_VALIDATE_URL = /^[-:.&#+()[\]$'*;@~!,?%=\/\w]+$/;

    // Attempt a function
    function attempt(func) {
        try {
            return func();
        }
        catch (e) {
            return e;
        }
    }

    // Check if a file exists at the specified URL
    function fileExists(url) {
        return new Promise(resolve =>
            Windows.Web.Http.HttpClient()
                .getAsync(new URI(url), Windows.Web.Http.HttpCompletionOption.responseHeadersRead)
                .done(e => resolve(e.isSuccessStatusCode), () => resolve(false))
        );
    }

    // Navigate to the specified absolute URL
    function navigate(webview, url, silent) {
        let resp = attempt(() => webview.navigate(url));
        let result = !(resp instanceof Error);

        if (!silent && !result) {
            console.error(`Unable to navigate to ${url}: ${resp.message}`);
        }
        return result;
    }

    // Show the favicon if available
    this.getFavicon = loc => {
        let host = new URI(loc).host;

        // Exit for cached ico location
        if (this.faviconLocs.has(host)) {
            loc = this.faviconLocs.get(host);
            if (loc) {
                this.favicon.src = loc;
            }
            else {
                this.hideFavicon();
            }
            return;
        }
        let protocol = loc.split(":")[0];

        // Hide favicon when the host cannot be resolved or the protocol is not http(s)
        if (!protocol.startsWith("http") || !host) {
            this.faviconLocs.set(host, "");
            this.hideFavicon();
            return;
        }

        loc = `${protocol}://${host}/favicon.ico`;

        // Check if there is a favicon in the root directory
        fileExists(loc).then(exists => {
            if (exists) {
                console.log(`Favicon found: ${loc}`);
                this.faviconLocs.set(host, loc);
                this.favicon.src = loc;
                return;
            }
            // Asynchronously check for a favicon in the web page markup
            console.log("Favicon not found in root. Checking the markup...");
            let asyncOp = this.webview.invokeScriptAsync("eval", `
                Object(Array.from(document.getElementsByTagName('link'))
                  .find(link => link.rel.includes('icon'))).href
            `);
            asyncOp.oncomplete = e => {
                loc = e.target.result || "";
                this.faviconLocs.set(host, loc);

                if (loc) {
                    console.log(`Found favicon in markup: ${loc}`);
                    this.favicon.src = loc;
                }
                else {
                    this.hideFavicon();
                }
            };
            asyncOp.onerror = e => {
                console.error(`Unable to find favicon in markup: ${e.message}`);
                this.faviconLocs.set(host, "");
            };
            asyncOp.start();
        });
    };

    // Hide the favicon
    this.hideFavicon = () => {
        this.favicon.src = "";
    };

    // Navigate to the specified location
    this.navigateTo = loc => {
        loc = LOC_CACHE.get(loc) || loc;

        // Check if the input value contains illegal characters
        let isUrl = RE_VALIDATE_URL.test(loc);
        if (isUrl && navigate(this.webview, loc, true)) {
            return;
        }
        let bingLoc = `https://www.bing.com/search?q=${encodeURIComponent(loc)}`;
        let locHTTP = `http://${loc}`;
        let locHTTPS = `https://${loc}`;

        console.log(`Unable to navigate to ${loc}\nAttemping to prepend http(s):// to URI...`);

        let uri = attempt(() => new URI(locHTTP));
        let isErr = uri instanceof Error;

        if (isErr || !isUrl || !uri.domain) {
            let message = isErr ? uri.message : "";
            console.log(`Prepend unsuccessful\nQuerying bing.com... "${loc}": ${message}`);

            LOC_CACHE.set(loc, bingLoc);
            navigate(this.webview, bingLoc);
        }
        else {
            // Check if the site supports https
            fileExists(locHTTPS).then(exists => {
                if (exists) {
                    LOC_CACHE.set(loc, locHTTPS);
                    navigate(this.webview, locHTTPS);
                }
            });

            // Get a head start on loading via http
            LOC_CACHE.set(loc, locHTTP);
            navigate(this.webview, locHTTP);
        }
    };

    // Show or hide the progress ring
    this.toggleProgressRing = state => {
        let style = this.progressRing.style;
        let isHidden = typeof state == "boolean" ? state : style.display == "none";
        style.display = isHidden ? "inline-block" : "none";
    };

    // Update the address bar with the given text and remove focus
    this.updateAddressBar = text => {
        this.urlInput.value = text;
        this.urlInput.blur();
    };

    // Hide the favicon when it fails to load
    this.favicon.addEventListener("error", () => {
        if (!this.favicon.src.startsWith("ms-appx://")) {
            this.hideFavicon();
        }
    });

    // Listen for the tweet button
    this.tweetIcon.addEventListener("click", () => {
        let domain = (this.currentUrl && new URI(this.currentUrl).host) || "microsoft.com";
        let path = "https://twitter.com/intent/tweet";
        let tags = ["Windows", "UWP"].map(encodeURIComponent);
        let text = encodeURIComponent(`I visited ${domain} in a browser built with HTML and JavaScript \uD83C\uDF32. Find out more here:`);
        let url = encodeURIComponent("http://bit.ly/1IDpBVA");
        this.navigateTo(`${path}?hashtags=${tags.join()}&text=${text}&url=${url}`);
    });

    // Listen for the loss of focus on the address bar to unselect the text
    this.urlInput.addEventListener("blur", () => getSelection().removeAllRanges());

    // Listen for focus on the address bar to auto-select the text
    // Use `setImmediate` to prevent the text from being immediately unselected
    this.urlInput.addEventListener("focus", e => setImmediate(() => e.target.select()));

    // Listen for the Enter key in the address bar to navigate to the specified URL
    this.urlInput.addEventListener("keypress", e => {
        if (e.keyCode === 13) {
            this.navigateTo(urlInput.value.trim());
        }
    });
});
<commit_msg>Add new ES6 unicode literal<commit_after>browser.on("init", function () {
    "use strict";

    const LOC_CACHE = new Map;
    const URI = Windows.Foundation.Uri;
    const RE_VALIDATE_URL = /^[-:.&#+()[\]$'*;@~!,?%=\/\w]+$/;

    // Attempt a function
    function attempt(func) {
        try {
            return func();
        }
        catch (e) {
            return e;
        }
    }

    // Check if a file exists at the specified URL
    function fileExists(url) {
        return new Promise(resolve =>
            Windows.Web.Http.HttpClient()
                .getAsync(new URI(url), Windows.Web.Http.HttpCompletionOption.responseHeadersRead)
                .done(e => resolve(e.isSuccessStatusCode), () => resolve(false))
        );
    }

    // Navigate to the specified absolute URL
    function navigate(webview, url, silent) {
        let resp = attempt(() => webview.navigate(url));
        let result = !(resp instanceof Error);

        if (!silent && !result) {
            console.error(`Unable to navigate to ${url}: ${resp.message}`);
        }
        return result;
    }

    // Show the favicon if available
    this.getFavicon = loc => {
        let host = new URI(loc).host;

        // Exit for cached ico location
        if (this.faviconLocs.has(host)) {
            loc = this.faviconLocs.get(host);
            if (loc) {
                this.favicon.src = loc;
            }
            else {
                this.hideFavicon();
            }
            return;
        }
        let protocol = loc.split(":")[0];

        // Hide favicon when the host cannot be resolved or the protocol is not http(s)
        if (!protocol.startsWith("http") || !host) {
            this.faviconLocs.set(host, "");
            this.hideFavicon();
            return;
        }

        loc = `${protocol}://${host}/favicon.ico`;

        // Check if there is a favicon in the root directory
        fileExists(loc).then(exists => {
            if (exists) {
                console.log(`Favicon found: ${loc}`);
                this.faviconLocs.set(host, loc);
                this.favicon.src = loc;
                return;
            }
            // Asynchronously check for a favicon in the web page markup
            console.log("Favicon not found in root. Checking the markup...");
            let asyncOp = this.webview.invokeScriptAsync("eval", `
                Object(Array.from(document.getElementsByTagName('link'))
                  .find(link => link.rel.includes('icon'))).href
            `);
            asyncOp.oncomplete = e => {
                loc = e.target.result || "";
                this.faviconLocs.set(host, loc);

                if (loc) {
                    console.log(`Found favicon in markup: ${loc}`);
                    this.favicon.src = loc;
                }
                else {
                    this.hideFavicon();
                }
            };
            asyncOp.onerror = e => {
                console.error(`Unable to find favicon in markup: ${e.message}`);
                this.faviconLocs.set(host, "");
            };
            asyncOp.start();
        });
    };

    // Hide the favicon
    this.hideFavicon = () => {
        this.favicon.src = "";
    };

    // Navigate to the specified location
    this.navigateTo = loc => {
        loc = LOC_CACHE.get(loc) || loc;

        // Check if the input value contains illegal characters
        let isUrl = RE_VALIDATE_URL.test(loc);
        if (isUrl && navigate(this.webview, loc, true)) {
            return;
        }
        let bingLoc = `https://www.bing.com/search?q=${encodeURIComponent(loc)}`;
        let locHTTP = `http://${loc}`;
        let locHTTPS = `https://${loc}`;

        console.log(`Unable to navigate to ${loc}\nAttemping to prepend http(s):// to URI...`);

        let uri = attempt(() => new URI(locHTTP));
        let isErr = uri instanceof Error;

        if (isErr || !isUrl || !uri.domain) {
            let message = isErr ? uri.message : "";
            console.log(`Prepend unsuccessful\nQuerying bing.com... "${loc}": ${message}`);

            LOC_CACHE.set(loc, bingLoc);
            navigate(this.webview, bingLoc);
        }
        else {
            // Check if the site supports https
            fileExists(locHTTPS).then(exists => {
                if (exists) {
                    LOC_CACHE.set(loc, locHTTPS);
                    navigate(this.webview, locHTTPS);
                }
            });

            // Get a head start on loading via http
            LOC_CACHE.set(loc, locHTTP);
            navigate(this.webview, locHTTP);
        }
    };

    // Show or hide the progress ring
    this.toggleProgressRing = state => {
        let style = this.progressRing.style;
        let isHidden = typeof state == "boolean" ? state : style.display == "none";
        style.display = isHidden ? "inline-block" : "none";
    };

    // Update the address bar with the given text and remove focus
    this.updateAddressBar = text => {
        this.urlInput.value = text;
        this.urlInput.blur();
    };

    // Hide the favicon when it fails to load
    this.favicon.addEventListener("error", () => {
        if (!this.favicon.src.startsWith("ms-appx://")) {
            this.hideFavicon();
        }
    });

    // Listen for the tweet button
    this.tweetIcon.addEventListener("click", () => {
        let domain = (this.currentUrl && new URI(this.currentUrl).host) || "microsoft.com";
        let path = "https://twitter.com/intent/tweet";
        let tags = ["Windows", "UWP"].map(encodeURIComponent);
        let text = encodeURIComponent(`I visited ${domain} in a browser built with HTML and JavaScript \u{1F332}. Find out more here:`);
        let url = encodeURIComponent("http://bit.ly/1IDpBVA");
        this.navigateTo(`${path}?hashtags=${tags.join()}&text=${text}&url=${url}`);
    });

    // Listen for the loss of focus on the address bar to unselect the text
    this.urlInput.addEventListener("blur", () => getSelection().removeAllRanges());

    // Listen for focus on the address bar to auto-select the text
    // Use `setImmediate` to prevent the text from being immediately unselected
    this.urlInput.addEventListener("focus", e => setImmediate(() => e.target.select()));

    // Listen for the Enter key in the address bar to navigate to the specified URL
    this.urlInput.addEventListener("keypress", e => {
        if (e.keyCode === 13) {
            this.navigateTo(urlInput.value.trim());
        }
    });
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Spacom::Addons::Design::Extensions
// @version      0.0.7
// @namespace    http://dimio.org/
// @description  Extends the functions of a ships constructor
// @author       dimio (dimio@dimio.org)
// @author       segrey
// @license      MIT
// @homepage     https://github.com/dimio/userscripts-spacom.ru-addons
// @supportURL   https://github.com/dimio/userscripts-spacom.ru-addons/issues
// @supportURL   https://spacom.ru/forum/discussion/47/polzovatelskie-skripty
// @encoding     utf-8
// @match        https://spacom.ru/?act=design*
// @include      https://spacom.ru/?act=design*
// @run-at       document-end
// ==/UserScript==
//
// An "All levels" addon - maked by segray (https://greasyfork.org/ru/scripts/27897-spacom-addons)
// console.log("Spacom::Addons::Design::Extensions booted");
const ERR_MSG = {
    NO_LIB: `Для работы дополнений необходимо установить Spacom.ru::Addons:

    https://github.com/dimio/userscripts-spacom.ru-addons/raw/master/Addons.user.js`,
};

(function (window) {
    window.unsafeWindow = window.unsafeWindow || window;
    const w = unsafeWindow;

    if (w.self !== w.top) {
        return;
    }
    if (!w.Addons) {
        w.showSmallMessage(ERR_MSG.NO_LIB);
        return;
    }
    if (!w.Addons.Design) {
        w.Addons.Design = {};
    }

    w.Addons.Design.ExtraInfo = {
        makeDesignInfoTemplate() {
            let designInfoTemplate = document.getElementById('design_info_template').innerHTML;

            designInfoTemplate = designInfoTemplate.replace("lazer_shots'] + ' ' : '' %>",
                "lazer_shots'] + ' ∑ ' + params['laser_power_summ'] + ' ' : '' %>");
            designInfoTemplate = designInfoTemplate.replace("lazer_defence'] + '% ' : '' %>",
                "lazer_defence'] + '% (' + params['laser_defence_hp'] + ' hp)  ' + params['laser_eq_hp'] + ' ' : '' %>");
            designInfoTemplate = designInfoTemplate.replace("cannon_defence'] + ' ' : '' %>",
                "cannon_defence'] + '  ' + params['cannon_hp'] + ' ' : '' %>");
            designInfoTemplate = designInfoTemplate.replace(/
\s*<button/,
                "<%= ( params['ship_power'] > '0') ? ' ' + params['ship_power'] : '' %>

<button");
            designInfoTemplate = designInfoTemplate.replace("cannon_targets'] + ' ' : '' %>",
                "cannon_targets'] + ' ∑ ' + params['cannon_power_summ'] + ' ' : '' %>");

            document.getElementById('design_info_template').innerHTML = designInfoTemplate;
        },
        calcLaserPowerSumm(params) {
            return params.lazer_power * params.lazer_shots;
        },
        calcLaserEqHp(params) {
            return Math.round(params.hp / (1 - (params.lazer_defence / 100)));
        },
        calcLaserHp(hp, laser_eq_hp) {
            return laser_eq_hp - hp;
        },
        calcCannonHp(params) {
            return params.hp + params.cannon_defence;
        },
        calcCannonPower(params) {
            return Math.round(params.cannon_power_summ / params.cannon_targets);
        },
        calcShipPower(params) {
            // Если считать приближенно (точность 95%), то мощь корабля -
            // это корень из произведения его живучести и суммарного урона.
            let shipPower = Math.sqrt(params.hp *
                (params.laser_power_summ + params.cannon_power + params.rocket_power)
            );
            shipPower /= 100; // to percents
            return Math.round(shipPower * 100) / 100; // round
        },
        init() {
            const self = this;
            const design = w.design;

            const _designCalc = design.calc;
            design.calc = function () {
                _designCalc.apply(this);

                design.params.laser_power_summ = self.calcLaserPowerSumm(design.params);
                design.params.laser_eq_hp = self.calcLaserEqHp(design.params);
                design.params.laser_defence_hp = self.calcLaserHp(
                    design.params.hp,
                    design.params.laser_eq_hp
                );

                design.params.cannon_power_summ = design.params.cannon_power;
                design.params.cannon_power = self.calcCannonPower(design.params);
                design.params.cannon_hp = self.calcCannonHp(design.params);

                design.params.ship_power = self.calcShipPower(design.params);
            };

            const _designDraw = design.draw;
            design.draw = function () {
                _designDraw.apply(this);
                $('#design_info').html(w.tmpl(document.getElementById('design_info_template').innerHTML, this));
            };

            this.makeDesignInfoTemplate();

            design.calc();
            design.draw();
        },
    };

    w.Addons.Design.DetailKnownLevel = {
        makeDetailInstanceTemplate() {
            let detailInstanceTemplate = document.getElementById('detail_instance').innerHTML;
            detailInstanceTemplate = detailInstanceTemplate.replace(/<%=level%>\n/,
                '<%=level%>
(<%=known_level%>)
');
            document.getElementById('detail_instance').innerHTML = detailInstanceTemplate;
        },
        init() {
            const template_components = w.design.template_components;
            for (const i in template_components) {
                if (template_components.hasOwnProperty(i)) {
                    template_components[i].known_level = template_components[i].max_level;
                }
            }

            const _Component = w.Component;
            w.Component = function () {
                // console.log(this);
                _Component.apply(this, arguments);
                const id = parseInt(this.component_id, 10);
                this.known_level = w.design.template_components[id].known_level;
            };

            this.makeDetailInstanceTemplate();
        },
    };

    w.Addons.Design.AllLevels = {
        // Author: segray (https://greasyfork.org/ru/scripts/27897-spacom-addons)
        enable() {
            const template_components = w.design.template_components;
            for (const i in template_components) {
                if (template_components.hasOwnProperty(i)) {
                    template_components[i].max_level = 100;
                }
            }
            w.design.draw();
        },
        disable() {
            const template_components = w.design.template_components;
            for (const i in template_components) {
                if (template_components.hasOwnProperty(i)) {
                    template_components[i].max_level = template_components[i]._max_level;
                }
            }
            w.design.draw();
        },
        init() {
            const self = this;
            $('#details_list').prepend('<input id="all_levels" type="checkbox"> все уровни');
            $('#all_levels').on('change', function () {
                if ($(this).is(':checked')) {
                    self.enable();
                }
                else {
                    self.disable();
                }
            });

            const template_components = w.design.template_components;
            for (const i in template_components) {
                if (template_components.hasOwnProperty(i)) {
                    template_components[i]._max_level = template_components[i].max_level;
                }
            }
            // Author: segray (https://greasyfork.org/ru/scripts/27897-spacom-addons)
        },
    };

    if (w.Design) {
        w.Addons.waitFor(w, 'design', () => {
            w.Addons.Design.ExtraInfo.init();
            w.Addons.Design.DetailKnownLevel.init();
            // be backwards-compatible with "spacom-addons" userscript by segrey
            if (!w.Addons.AllLevels) {
                w.Addons.Design.AllLevels.init();
            }
        });
    }

})(window);
<commit_msg>chore(Design): accord to new game mechanic, add "Damage per Rent" for ship design<commit_after>// ==UserScript==
// @name         Spacom.Addons.Design.Extensions
// @version      0.1.0
// @namespace    http://dimio.org/
// @description  Extends the functions of a ships constructor
// @author       dimio (dimio@dimio.org)
// @author       segrey
// @license      MIT
// @homepage     https://github.com/dimio/userscripts-spacom.ru-addons
// @supportURL   https://github.com/dimio/userscripts-spacom.ru-addons/issues
// @supportURL   https://spacom.ru/forum/discussion/47/polzovatelskie-skripty
// @encoding     utf-8
// @match        http*://spacom.ru/?act=game/design*
// @include      http*://spacom.ru/?act=game/design*
// @run-at       document-end
// ==/UserScript==
//
// An "All levels" addon - developed by segray (https://greasyfork.org/ru/scripts/27897-spacom-addons)
// console.log("Spacom.Addons.Design.Extensions booted");
const ERR_MSG = {
  NO_LIB: `Для работы дополнений необходимо установить Spacom.Addons:

    https://github.com/dimio/userscripts-spacom.ru-addons/raw/master/Addons/Addons.user.js`,
};
const COMPONENT_MAX_LEVEL = 30;

(function (window) {
  window.unsafeWindow = window.unsafeWindow || window;
  const w = unsafeWindow;

  if (w.self !== w.top) {
    return;
  }
  if (!w.Addons) {
    w.showSmallMessage(ERR_MSG.NO_LIB);
    return;
  }
  if (!w.Addons.Design) {
    w.Addons.Design = {};
  }

  w.Addons.Design.ExtraInfo = {
    makeDesignInfoTemplate() {
      let designInfoTemplate = document.getElementById(
          'design_info_template').innerHTML;
      designInfoTemplate = designInfoTemplate.replace(
          "lazer_shots'] + ' ' : '' %>",
          "lazer_shots'] + ' ∑ ' + params['laser_power_sum'] + ' ' : '' %>");
      designInfoTemplate = designInfoTemplate.replace(
          "lazer_defence'] + '% ' : '' %>",
          "lazer_defence'] + '% (' + params['laser_defence_hp'] + ' hp)  ' + params['laser_eq_hp'] + '' : '' %>");
      designInfoTemplate = designInfoTemplate.replace(
          "cannon_defence'] + ' ' : '' %>",
          "cannon_defence'] + '  ' + params['cannon_hp'] + ' ' : '' %>");
      designInfoTemplate = designInfoTemplate.replace(
          "cannon_targets'] + ' ' : '' %>",
          "cannon_targets'] + ' ∑ ' + params['cannon_power_sum'] + ' ' : '' %>");

      const designInfoTemplateTail = `'' %>
        <%= ( params['ship_power'] > '0' ) ?
        ' ' + params['ship_power']
        + ' '
        : '' %>
        <%= ( params['ship_damage_per_rent'] > '0' ) ?
        ' ' + params['ship_damage_per_rent']
        : '' %>

`;
      designInfoTemplate = designInfoTemplate.replace(/'' %>\s*<\/div>/,
          designInfoTemplateTail);

      document.getElementById(
          'design_info_template').innerHTML = designInfoTemplate;
    },
    calcLaserPowerSum(params) {
      return params.lazer_power * params.lazer_shots;
    },
    calcLaserEqHp(params) {
      return Math.round(params.hp / (1 - (params.lazer_defence / 100)));
    },
    calcLaserHp(hp, laser_eq_hp) {
      return laser_eq_hp - hp;
    },
    calcCannonHp(params) {
      return params.hp + params.cannon_defence;
    },
    calcCannonPower(params) {
      return Math.round(params.cannon_power_sum / params.cannon_targets);
    },
    calcShipStatsTotal(...args) {
      return args.reduce((total, current) => total + current, 0);
    },
    calcShipPower(params) {
      // Если считать приближенно (точность 95%), то мощь корабля -
      // это корень из произведения его живучести и суммарного урона.
      let shipPower = Math.sqrt(params.hp *
          this.calcShipStatsTotal(params.laser_power_sum,
              params.cannon_power_sum, params.rocket_power)
      );
      return Math.round(shipPower);
    },
    calcShipDpR(params) {
      return +(this.calcShipStatsTotal(
          params.laser_power_sum, params.cannon_power_sum, params.rocket_power)
          / params.money_rent).toFixed(2);
    },
    init() {
      const self = this;
      const design = w.design;
      this.makeDesignInfoTemplate();

      const _designCalc = design.calc;
      design.calc = function () {
        _designCalc.apply(this);

        design.params.laser_power_sum = self.calcLaserPowerSum(design.params);
        design.params.laser_eq_hp = self.calcLaserEqHp(design.params);
        design.params.laser_defence_hp = self.calcLaserHp(
            design.params.hp,
            design.params.laser_eq_hp
        );

        design.params.cannon_power_sum = design.params.cannon_power;
        design.params.cannon_power = self.calcCannonPower(design.params);
        design.params.cannon_hp = self.calcCannonHp(design.params);

        design.params.ship_power = self.calcShipPower(design.params);
        design.params.ship_damage_per_rent = self.calcShipDpR(design.params);
      };

      const _designDraw = design.draw;
      design.draw = function () {
        _designDraw.apply(this);
        $('#design_info').html(
            w.tmpl(document.getElementById('design_info_template').innerHTML,
                this));
      };

      design.calc();
      design.draw();
    },
  };

  //FIXME: known levels not show for non-new designs
  w.Addons.Design.DetailKnownLevel = {
    makeDetailInstanceTemplate() {
      let detailInstanceTemplate = document.getElementById(
          'detail_instance').innerHTML;
      detailInstanceTemplate = detailInstanceTemplate.replace(/<%=level%>\n/,
          '<%=level%>
(<%=known_level%>)
');
      document.getElementById(
          'detail_instance').innerHTML = detailInstanceTemplate;
    },
    init() {
      this.makeDetailInstanceTemplate();

      const tc = w.design.template_components;
      for (const i in tc) {
        if (tc.hasOwnProperty(i)) {
          tc[i].known_level = tc[i].max_level;
        }
      }

      const _Component = w.Component;
      w.Component = function () {
        _Component.apply(this, arguments);
        const id = parseInt(this.component_id, 10);
        this.known_level = w.design.template_components[id].known_level;
      };
    },
  };

  w.Addons.Design.AllLevels = {
    // Based on AllLevels by segray (https://greasyfork.org/ru/scripts/27897-spacom-addons)
    enable() {
      w.design.template_components.forEach(c => {
        c.max_level = COMPONENT_MAX_LEVEL
      });
      w.design.draw();
    },
    disable() {
      w.design.template_components.forEach(c => {
        c.max_level = c._max_level
      });
      w.design.draw();
    },
    init() {
      const self = this;
      $('#details_list').prepend(
          '<input id="all_levels" type="checkbox"> все уровни');
      $('#all_levels').on('change', function () {
        if ($(this).is(':checked')) {
          self.enable();
        } else {
          self.disable();
        }
      });

      w.design.template_components.forEach(c => {
        c._max_level = c.max_level
      });
    },
  };

  if (w.Design) {
    w.Addons.waitFor(w, 'design', () => {
      w.Addons.Design.ExtraInfo.init();
      w.Addons.Design.DetailKnownLevel.init();
      // be backwards-compatible with "spacom-addons" userscript by segrey
      if (!w.Addons.AllLevels) {
        w.Addons.Design.AllLevels.init();
      }
    });
  }

})(window);
<|endoftext|>


<commit_before>
if(!('contains' in String.prototype))// polyfill for chrome so str.contains actually works.
	String.prototype.contains = function(str, startIndex) { return -1 !== String.prototype.indexOf.call(this, str, startIndex); };

var datavar; //le data variable
datavar = {'limit': '50'};//party bitches
var loading = false;//shits not loading
var after;//yup
var url; //global url. cause functions aint shit

$(document).ready(function() {//add a check for /false or /true and set the includepics var appropriatly
	if(localStorage.getItem("includepics") == null){
		localStorage.setItem("includepics", "true");
		$('#picstrue').prop('checked', true);
		console.log("null - set all true");
		checkurl();
	} else if (localStorage.getItem("includepics") == 'true'){
		$('#picstrue').prop('checked', true);
		console.log("true - set radio true");
		checkurl();
	} else if (localStorage.getItem("includepics") == 'false'){
		$('#picsfalse').prop('checked', true);
		console.log("false - set radio false");
		//set include pics radio to false so we dont break the rest of the code -_-
		checkurl();
	}

	function checkurl(){
		var sub = window.location.hash; //gets the hash varible we built up earlyer
		var subreddits = sub.replace('#', ' ').trimLeft();//removes the hash and trims it up
		console.log(subreddits);//logging dis bitch
		if (localStorage.getItem("includepics") == 'true') {
			if(window.location.hash){
				url = "http://www.reddit.com/r/pics+"+ subreddits +".json";
				$('.alert').remove();
				imgload(datavar);
			}else{
				url = "http://www.reddit.com/r/pics.json";
				$('.alert').remove();
				imgload(datavar);
			}
		} else if (localStorage.getItem("includepics") == 'false' && window.location.hash) {
			url = "http://www.reddit.com/r/"+ subreddits +".json";
			$('.alert').remove();
			$( ".pics" ).remove();
			imgload(datavar);
		} else{
			$('.images').append('

Add Subreddits plz

');
		}
	}

	function imgload(datavar){
		$.ajax({
			url: url,
			jsonp: "jsonp",
			data: datavar,
			dataType: "jsonp"
		}).done(function(json){
			$('.alert').remove();
			loading = false;
			console.log(json);
			after = json.data.after;
			var finalhtml;
			for (var r = 0; r < json.data.children.length; r++){
				var image = json.data.children[r].data.url;
				var subreddit = json.data.children[r].data.subreddit;
				var title = json.data.children[r].data.title;
				if (image.contains("i.imgur")) {
					if (json.data.children[r].data.over_18 === true) {
						finalhtml += '

'+ title +'

';
						//$('.images').append('

'+ title +'

');
					}else if (json.data.children[r].data.over_18 === false){
						finalhtml += '

'+ title +'

';
						//$('.images').append('

'+ title +'

');
					}
				}
			}
			$('.images').append(finalhtml);//appends the html we built

		});
	}
	$('#addsub').submit(function() {
		var sub = document.getElementById("subname").value;
		if (window.location.hash){
			window.location.hash += "+" + sub;
			checkurl();
			return false;
		} else{
			window.location.hash += sub;
			checkurl();
			return false;
		}
	});

	function loadmore(){
		console.log(after);
		datavar = {'limit': '50', 'after':after};
		checkurl();
	}

	$(window).scroll(function(){
		if($(window).scrollTop()==$(document).height()-$(window).height()){
			console.log("bottom!");
			if (loading == false){
				loadmore();
				loading = true;
			} else if (loading == true){
				console.log("loading...");
			}
		}
	});
	$( "#picstrue" ).click(function(){
		localStorage.setItem("includepics", "true");
		$( ".image" ).remove();
		$('.alert').remove();
		//set the window to top
		checkurl();
	});
	$( "#picsfalse" ).click(function(){
		localStorage.setItem("includepics", "false");
		$( ".image" ).remove();
		$('.images').prepend('

Add Subreddits plz

');
		//set the window to top
		checkul();
	});
	/*$("nsfw:checked"){
		//display: block;
	}
	$("nsfw:unchecked"){
		//display: none;
	}*/

	$("#reload").click(function(){//remove the auto-reload on adding subreddits?
		//set the window back to top
		checkurl();
	});

});
<commit_msg>simplifyed js.<commit_after>
if(!('contains' in String.prototype))// polyfill for chrome so str.contains actually works.
	String.prototype.contains = function(str, startIndex) { return -1 !== String.prototype.indexOf.call(this, str, startIndex); };

var datavar = {'limit': '50'};//party bitches
var loading = false;//shits not loading
var after;//yup

$(document).ready(function() {//add a check for /false or /true and set the includepics var appropriatly
	if(localStorage.getItem("includepics") == null){
		localStorage.setItem("includepics", "true");
		$('#picstrue').prop('checked', true);
		console.log("null - set all true");
		checkurl();
	} else if (localStorage.getItem("includepics") == 'true'){
		$('#picstrue').prop('checked', true);
		console.log("true - set radio true");
		checkurl();
	} else if (localStorage.getItem("includepics") == 'false'){
		$('#picsfalse').prop('checked', true);
		console.log("false - set radio false");
		//set include pics radio to false so we dont break the rest of the code -_-
		checkurl();
	}

	function checkurl(){
		var sub = window.location.hash; //gets the hash varible we built up earlyer
		var subreddits = sub.replace('#', ' ').trimLeft();//removes the hash and trims it up
		console.log(subreddits);//logging dis bitch
		if (localStorage.getItem("includepics") == 'true') {
			if(window.location.hash){
				var url = "http://www.reddit.com/r/pics+"+ subreddits +".json";
				$('.alert').remove();
				imgload(url);
			}else{
				var url = "http://www.reddit.com/r/pics.json";
				$('.alert').remove();
				imgload(url);
			}
		} else if (localStorage.getItem("includepics") == 'false' && window.location.hash) {
			var url = "http://www.reddit.com/r/"+ subreddits +".json";
			$('.alert').remove();
			$( ".pics" ).remove();
			imgload(url);
		} else{
			$('.images').append('

Add Subreddits plz

');
		}
	}

	function imgload(url){
		$.ajax({
			url: url,
			jsonp: "jsonp",
			data: datavar,
			dataType: "jsonp"
		}).done(function(json){
			$('.alert').remove();
			loading = false;
			console.log(json);
			after = json.data.after;
			var finalhtml;
			for (var r = 0; r < json.data.children.length; r++){
				var image = json.data.children[r].data.url;
				var subreddit = json.data.children[r].data.subreddit;
				var title = json.data.children[r].data.title;
				if (image.contains("i.imgur")) {
					if (json.data.children[r].data.over_18 === true) {
						finalhtml += '

'+ title +'

';
					}else if (json.data.children[r].data.over_18 === false){
						finalhtml += '

'+ title +'

';
					}
				}
			}
			$('.images').append(finalhtml);//appends the html we built

		});
	}

	$('#addsub').submit(function() {
		var sub = document.getElementById("subname").value;
		if (window.location.hash){
			window.location.hash += "+" + sub;
			checkurl();
			return false;
		} else{
			window.location.hash += sub;
			checkurl();
			return false;
		}
	});

	$(window).scroll(function(){
		if($(window).scrollTop()==$(document).height()-$(window).height()){
			console.log("bottom!");
			if (loading == false){
				console.log(after);
				datavar = {'limit': '50', 'after':after};
				checkurl();
				loading = true;
			} else if (loading == true){
				console.log("loading...");
			}
		}
	});

	$( "#picstrue" ).click(function(){
		localStorage.setItem("includepics", "true");
		$( ".image" ).remove();
		$('.alert').remove();
		//set the window to top
		checkurl();
	});

	$( "#picsfalse" ).click(function(){
		localStorage.setItem("includepics", "false");
		$( ".image" ).remove();
		$('.images').prepend('

Add Subreddits plz

');
		//set the window to top
		checkurl();
	});

	/*$("nsfw:checked"){
		//display: block;
	}
	$("nsfw:unchecked"){
		//display: none;
	}*/

	$("#reload").click(function(){//remove the auto-reload on adding subreddits?
		//set the window back to top
		checkurl();
	});

	/*
	window.scroll
		pagehieght = display area
			when .images go 100px above window.top
				set div height to image height
				remove image
				set visibility to hidden
			when .images come within 100px of window.top
				set visibility to show
				add image back (grab the imgur url from the array of images that imgload will build)
			when .images go 100px below window.bottom
				remove image
				setvisibility to hidden
			when .images come within 100px of window.bottom
				setvisibility to show
				add image back

	*/

});
<|endoftext|>


<commit_before>(function (root) {
	var extraIncludes = [];
	var init = false;
	var inc = {
		p5Version: '0.5.15',
		require: function (name) {
			inc.includes[name].required = true;
		},
		addInclude: function (path) {
			if (!init) {
				extraIncludes.push(path);
				return;
			}
			if (!(~path.indexOf(':')) && path[0] !== ".") {
				path = 'http://www.unclejasonteachesprogramming.com/gitjs/p5-sketches/master/' + path;
			}
			var script = document.createElement("script");
			script.src = path;
			script.async = false;
			document.head.appendChild(script);
		},
		includes: {
			"shapes": {
				"path": "includes/shapes.js",
				"description": "Creates functions for generating simple but not trivial geometric shapes, such as stars and hearts.",
				"required": false
			},
			"particle": {
				"path": "includes/Particle.js",
				"description": "Custom simple UJTP particle class.",
				"required": false
			},
			"p5.play": {
				"path": "https://cdn.rawgit.com/molleindustria/p5.play/master/lib/p5.play.js",
				"description": "p5.play provides sprites, animations, input and collision functions for games and gamelike applications. Created by Paolo Pedercini.",
				"required": "false"
			}
		}
	};

	function addEvent(element, eventName, fn) {
		if (element.addEventListener) {
			element.addEventListener(eventName, fn, false);
		} else if (element.attachEvent) {
			element.attachEvent('on' + eventName, fn);
		}
	}
	if (root.preInit && typeof root.preInit == 'function') {
		root.preInit(inc);
	}
	init = true;
	inc.addInclude('https://cdnjs.cloudflare.com/ajax/libs/p5.js/' + inc.p5Version + '/p5.min.js');
	for (var lib in inc.includes) {
		if (inc.includes[lib].required) {
			if (typeof inc.includes[lib].path == 'function') {
				inc.addInclude(inc.includes[lib].path());
			} else {
				inc.addInclude(inc.includes[lib].path);
			}
		}
	}
	for (var i = 0; i < extraIncludes.length; i++) {
		inc.addInclude(extraIncludes[i]);
	}
}(this));
<commit_msg>Added p5.gui to includes<commit_after>(function (root) {
	var extraIncludes = [];
	var init = false;
	var inc = {
		p5Version: '0.5.15',
		require: function (name) {
			inc.includes[name].required = true;
		},
		addInclude: function (path) {
			if (Array.isArray(path)) {
				for (var i = 0; i < path.length; i++) {
					inc.addInclude(path[i]);
				}
			}
			if (!init) {
				extraIncludes.push(path);
				return;
			}
			if (!(~path.indexOf(':')) && path[0] !== ".") {
				path = 'http://www.unclejasonteachesprogramming.com/gitjs/p5-sketches/master/' + path;
			}
			var script = document.createElement("script");
			script.src = path;
			script.async = false;
			document.head.appendChild(script);
		},
		includes: {
			"shapes": {
				"path": "includes/shapes.js",
				"description": "Creates functions for generating simple but not trivial geometric shapes, such as stars and hearts.",
				"required": false
			},
			"particle": {
				"path": "includes/Particle.js",
				"description": "Custom simple UJTP particle class.",
				"required": false
			},
			"p5.play": {
				"path": "https://cdn.rawgit.com/molleindustria/p5.play/master/lib/p5.play.js",
				"description": "p5.play provides sprites, animations, input and collision functions for games and gamelike applications. Created by Paolo Pedercini.",
				"required": false
			},
			"p5.gui": {
				"path": [
					"https://cdn.rawgit.com/bitcraftlab/p5.gui/08ac86b7/libraries/p5.gui.js",
					"https://cdn.rawgit.com/bitcraftlab/p5.gui/08ac86b7/libraries/quicksettings.js"
				],
				"description": "p5.gui generates a graphical user interface for your p5.js sketches.",
				"required": false
			}
		}
	};

	function addEvent(element, eventName, fn) {
		if (element.addEventListener) {
			element.addEventListener(eventName, fn, false);
		} else if (element.attachEvent) {
			element.attachEvent('on' + eventName, fn);
		}
	}
	if (root.preInit && typeof root.preInit == 'function') {
		root.preInit(inc);
	}
	init = true;
	inc.addInclude('https://cdnjs.cloudflare.com/ajax/libs/p5.js/' + inc.p5Version + '/p5.min.js');
	for (var lib in inc.includes) {
		if (inc.includes[lib].required) {
			if (typeof inc.includes[lib].path == 'function') {
				inc.addInclude(inc.includes[lib].path());
			} else {
				inc.addInclude(inc.includes[lib].path);
			}
		}
	}
	for (var i = 0; i < extraIncludes.length; i++) {
		inc.addInclude(extraIncludes[i]);
	}
}(this));
<|endoftext|>


<commit_before>// @flow
import sinon from 'sinon';
import assert from 'assert';
import {ObjectID,MongoClient} from 'mongodb';
import {
  connect as connectMongo,
  dispose as disposeMongo
} from './_MongoConnect';

import {
  CRUDRepository,
  MappedRepository
} from '../src/Repository';

import { Observable } from 'rxjs/Rx';

const MONGO_URL = 'mongodb://mongo:27017/integration_tests';

describe('CRUD Repositories',()=>{
  let sandbox,mocks,testRepo;
  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    mocks = {};
    testRepo = CRUDRepository('tests',()=>connectMongo(MONGO_URL));
  });
  afterEach(() => {
    return disposeMongo(MONGO_URL);
  });
  describe('insert', () => {
    it('should accept and array and return observable of inserted items',async ()=>{
      let res = await testRepo
      .insert([{a:'b'},{a:'b'}])
      .do(item=>assert.equal(item.a,'b','Should return observable of added items'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 2, 'All items should be returned');
    });
    it('should also accept an observable of items',async ()=>{
      let itemObservable = Observable.range(1,10).map(i=>({i}));

      let res = await testRepo
      .insert(itemObservable)
      .toArray()
      .toPromise();

      assert.equal(res.length, 10, 'All items should be returned');
    });
    it('should deal with enormous amounts of data',async function(){
      this.timeout(10000);

      let hugeness = 100000;

      let itemFactory = Observable
        .range(1, hugeness)
        .map(i=>({foo:5}));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({})
      // Accumulate count
      .reduce((acc, item) => acc + 1, 0)
      .toPromise();

      assert.equal(res, hugeness,'Should return all results');
    })
  });
  describe('query', () => {
    it('should return added items',async ()=>{
      let itemFactory = Observable
        .range(0, 100)
        .map(i=>({
          even:(i%2 === 0),
          foo:i
        }));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({
        foo:{$gte:20},
        even:true
      })
      .do(item=>assert.ok(item.foo,'Each item should contain "foo" key'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 40,'Should return all results');
    });
    it('should handle multiple simultaneous queries',async ()=>{
      const numberOfItems = 1000;
      let itemFactory = Observable
        .range(0, numberOfItems)
        .map(i=>({
          even:(i%2===0),
        }));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      const numberOfQueries = 100;

      const res = await Observable
      .range(0, numberOfQueries)
      .mapTo({})
      .flatMap(query=>testRepo.query(query))
      .toArray()
      .toPromise();

      assert.equal(res.length, numberOfQueries*numberOfItems,'Should return all results');
    });
    it('should handle result limit',async ()=>{
      let itemFactory = Observable
        .range(0, 1000)
        .map(i=>({foo:'bar'}));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({},{limit:100})
      .toArray()
      .toPromise();

      assert.equal(res.length, 100,'Should return all results');
    });
  });
  describe('update',()=>{
    it('should update items accordingly and return corrosponding ids',async()=>{
      let itemFactory = Observable
        .range(1, 50)
        .map(i=>({aNumber:5}));

      let insertedObs = testRepo
      .insert(itemFactory)
      .do(item=>assert.equal(item.aNumber,5,'Field value should be that of inserted value'));

      let newItems = insertedObs
      .map(item=>({...item,aNumber:6}));

      let res = await testRepo
      .update(newItems)
      .do(id=>assert.ok(id,'Should return ids'))
      .toArray()
      .flatMap(ids=>testRepo.query({_id:{$in:ids}}))
      .do(item=>assert.equal(item.aNumber,6,'Documents should have been updated'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 50,'Should return all results');
    })

    it('should upsert items if the option is specified', async () => {
      let itemFactory = Observable
      .range(1, 50)
      .map(i => ({aNumber: 5}));

      let insertedObs = testRepo
      .insert(itemFactory)
      .do(item => assert.equal(item.aNumber, 5, 'Field value should be that of inserted value'));

      let newItems = Observable.merge(
        insertedObs.map(item => ({...item, aNumber: 6})),
        Observable.range(1, 10).map(_ => ({_id: ObjectID(), aNumber: 6}))
      );

      let res = await testRepo
      .update(newItems, {upsert: true})
      .do(id => assert.ok(id, 'Should return ids'))
      .toArray()
      .flatMap(ids => testRepo.query({_id: {$in: ids}}))
      .do(item => assert.equal(item.aNumber, 6, 'Documents should have been updated'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 60, 'Should return all results');
    })
  });
  describe('delete',()=>{
    it('should delete items accordingly and return corrosponding ids',async()=>{
      let itemFactory = Observable
        .range(1, 50)
        .map(i=>({aNumber:5}));

      let insertedObs = testRepo
      .insert(itemFactory);

      await testRepo
      .delete(insertedObs.take(10))
      .toPromise();

      let res = await testRepo
      .query({})
      .toArray()
      .toPromise();

      assert.equal(res.length, 40,'10 items should have been deleted');
    });
  });
});
<commit_msg>Modify test to use an upsert method instead of option<commit_after>// @flow
import sinon from 'sinon';
import assert from 'assert';
import {ObjectID,MongoClient} from 'mongodb';
import {
  connect as connectMongo,
  dispose as disposeMongo
} from './_MongoConnect';

import {
  CRUDRepository,
  MappedRepository
} from '../src/Repository';

import { Observable } from 'rxjs/Rx';

const MONGO_URL = 'mongodb://mongo:27017/integration_tests';

describe('CRUD Repositories',()=>{
  let sandbox,mocks,testRepo;
  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    mocks = {};
    testRepo = CRUDRepository('tests',()=>connectMongo(MONGO_URL));
  });
  afterEach(() => {
    return disposeMongo(MONGO_URL);
  });
  describe('insert', () => {
    it('should accept and array and return observable of inserted items',async ()=>{
      let res = await testRepo
      .insert([{a:'b'},{a:'b'}])
      .do(item=>assert.equal(item.a,'b','Should return observable of added items'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 2, 'All items should be returned');
    });
    it('should also accept an observable of items',async ()=>{
      let itemObservable = Observable.range(1,10).map(i=>({i}));

      let res = await testRepo
      .insert(itemObservable)
      .toArray()
      .toPromise();

      assert.equal(res.length, 10, 'All items should be returned');
    });
    it('should deal with enormous amounts of data',async function(){
      this.timeout(10000);

      let hugeness = 100000;

      let itemFactory = Observable
        .range(1, hugeness)
        .map(i=>({foo:5}));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({})
      // Accumulate count
      .reduce((acc, item) => acc + 1, 0)
      .toPromise();

      assert.equal(res, hugeness,'Should return all results');
    })
  });
  describe('query', () => {
    it('should return added items',async ()=>{
      let itemFactory = Observable
        .range(0, 100)
        .map(i=>({
          even:(i%2 === 0),
          foo:i
        }));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({
        foo:{$gte:20},
        even:true
      })
      .do(item=>assert.ok(item.foo,'Each item should contain "foo" key'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 40,'Should return all results');
    });
    it('should handle multiple simultaneous queries',async ()=>{
      const numberOfItems = 1000;
      let itemFactory = Observable
        .range(0, numberOfItems)
        .map(i=>({
          even:(i%2===0),
        }));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      const numberOfQueries = 100;

      const res = await Observable
      .range(0, numberOfQueries)
      .mapTo({})
      .flatMap(query=>testRepo.query(query))
      .toArray()
      .toPromise();

      assert.equal(res.length, numberOfQueries*numberOfItems,'Should return all results');
    });
    it('should handle result limit',async ()=>{
      let itemFactory = Observable
        .range(0, 1000)
        .map(i=>({foo:'bar'}));

      await testRepo
      .insert(itemFactory)
      .toPromise();

      let res = await testRepo.query({},{limit:100})
      .toArray()
      .toPromise();

      assert.equal(res.length, 100,'Should return all results');
    });
  });
  describe('update',()=>{
    it('should update items accordingly and return corrosponding ids',async()=>{
      let itemFactory = Observable
        .range(1, 50)
        .map(i=>({aNumber:5}));

      let insertedObs = testRepo
      .insert(itemFactory)
      .do(item=>assert.equal(item.aNumber,5,'Field value should be that of inserted value'));

      let newItems = insertedObs
      .map(item=>({...item,aNumber:6}));

      let res = await testRepo
      .update(newItems)
      .do(id=>assert.ok(id,'Should return ids'))
      .toArray()
      .flatMap(ids=>testRepo.query({_id:{$in:ids}}))
      .do(item=>assert.equal(item.aNumber,6,'Documents should have been updated'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 50,'Should return all results');
    })
  });
  describe('upsert',()=>{
    it('should upsert items and return corrosponding ids', async () => {
      let itemFactory = Observable
      .range(1, 50)
      .map(i => ({aNumber: 5}));

      let insertedObs = testRepo
      .insert(itemFactory)
      .do(item => assert.equal(item.aNumber, 5, 'Field value should be that of inserted value'));

      let newItems = Observable.merge(
        insertedObs.map(item => ({...item, aNumber: 6})),
        Observable.range(1, 10).map(_ => ({_id: ObjectID(), aNumber: 6}))
      );

      let res = await testRepo
      .upsert(newItems)
      .do(id => assert.ok(id, 'Should return ids'))
      .toArray()
      .flatMap(ids => testRepo.query({_id: {$in: ids}}))
      .do(item => assert.equal(item.aNumber, 6, 'Documents should have been updated'))
      .toArray()
      .toPromise();

      assert.equal(res.length, 60, 'Should return all results');
    })
  });
  describe('delete',()=>{
    it('should delete items accordingly and return corrosponding ids',async()=>{
      let itemFactory = Observable
        .range(1, 50)
        .map(i=>({aNumber:5}));

      let insertedObs = testRepo
      .insert(itemFactory);

      await testRepo
      .delete(insertedObs.take(10))
      .toPromise();

      let res = await testRepo
      .query({})
      .toArray()
      .toPromise();

      assert.equal(res.length, 40,'10 items should have been deleted');
    });
  });
});
<|endoftext|>