<commit_before>import React, {useContext} from 'react';
import {ScrollView, StyleSheet, Text, Image, FlatList, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import {CoordinatorLayout, NavigationBar, TabBar, TabBarItem, TabLayout} from 'navigation-react-native';

export default ({follows}) => {
  const {stateNavigator} = useContext(NavigationContext);
  return (
    <CoordinatorLayout>
      <NavigationBar title="Notifications" barTintColor={Platform.OS === 'android' ? '#fff' : null}>
        <TabBar barTintColor="#fff" selectedTintColor="deepskyblue" />
      </NavigationBar>
      <TabBar selectedTintColor="deepskyblue">
        <TabBarItem title="All">
          <ScrollView
            nestedScrollEnabled={true}
            contentInsetAdjustmentBehavior="automatic"
            style={styles.view}>
            <FlatList
                data={follows}
                keyExtractor={(item, index) => '' + index}
                renderItem={({item: {id, name, logo}}) => (
                  <TouchableHighlight
                    underlayColor="white"
                    onPress={() => {
                      stateNavigator.navigate('timeline', {id});
                  }}>
                  <View style={styles.follow}>
                    <View>
                      <Image style={styles.logo} source={logo} />
                      <View style={styles.details}>
                      <Text style={styles.name}>{name}</Text>
                      <Text>followed you.</Text>
                      </View>
                    </View>
                  </View>
                </TouchableHighlight>
              )} />
          </ScrollView>
        </TabBarItem>
        <TabBarItem title="Mentions">
        </TabBarItem>
      </TabBar>
    </CoordinatorLayout>
  );
};

const styles = StyleSheet.create({
  view: {
    paddingLeft: 20,
    paddingRight: 20,
  },
  follow: {
    flexDirection: 'row',
    paddingTop: 10,
    paddingBottom: 15,
    borderBottomColor: '#ccd6dd',
    borderBottomWidth: 1,
  },
  icon: {
    marginRight: 10,
  },
  details: {
    flexDirection: 'row',
  },
  name: {
    fontWeight: 'bold',
    paddingRight: 4,
  },
  logo: {
    width: 35,
    height: 35,
    borderRadius: 17.5,
    marginRight: 5,
    marginBottom: 10,
  },
});
<commit_msg>Removed unused import<commit_after>import React, {useContext} from 'react';
import {ScrollView, StyleSheet, Text, Image, FlatList, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import {CoordinatorLayout, NavigationBar, TabBar, TabBarItem} from 'navigation-react-native';

export default ({follows}) => {
  const {stateNavigator} = useContext(NavigationContext);
  return (
    <CoordinatorLayout>
      <NavigationBar title="Notifications" barTintColor={Platform.OS === 'android' ? '#fff' : null}>
        <TabBar barTintColor="#fff" selectedTintColor="deepskyblue" />
      </NavigationBar>
      <TabBar selectedTintColor="deepskyblue">
        <TabBarItem title="All">
          <ScrollView
            nestedScrollEnabled={true}
            contentInsetAdjustmentBehavior="automatic"
            style={styles.view}>
            <FlatList
                data={follows}
                keyExtractor={(item, index) => '' + index}
                renderItem={({item: {id, name, logo}}) => (
                  <TouchableHighlight
                    underlayColor="white"
                    onPress={() => {
                      stateNavigator.navigate('timeline', {id});
                  }}>
                  <View style={styles.follow}>
                    <View>
                      <Image style={styles.logo} source={logo} />
                      <View style={styles.details}>
                      <Text style={styles.name}>{name}</Text>
                      <Text>followed you.</Text>
                      </View>
                    </View>
                  </View>
                </TouchableHighlight>
              )} />
          </ScrollView>
        </TabBarItem>
        <TabBarItem title="Mentions">
        </TabBarItem>
      </TabBar>
    </CoordinatorLayout>
  );
};

const styles = StyleSheet.create({
  view: {
    paddingLeft: 20,
    paddingRight: 20,
  },
  follow: {
    flexDirection: 'row',
    paddingTop: 10,
    paddingBottom: 15,
    borderBottomColor: '#ccd6dd',
    borderBottomWidth: 1,
  },
  icon: {
    marginRight: 10,
  },
  details: {
    flexDirection: 'row',
  },
  name: {
    fontWeight: 'bold',
    paddingRight: 4,
  },
  logo: {
    width: 35,
    height: 35,
    borderRadius: 17.5,
    marginRight: 5,
    marginBottom: 10,
  },
});
<|endoftext|>


<commit_before>;(function (global) {
  'use strict'

  var $ = global.jQuery
  var GOVUK = global.GOVUK || {}

  function ShowHideContent () {
    var self = this

    // Radio and Checkbox selectors
    var selectors = {
      namespace: 'ShowHideContent',
      radio: '.block-label[data-target] input[type="radio"]',
      checkbox: '.block-label[data-target] input[type="checkbox"]'
    }

    // Escape name attribute for use in DOM selector
    function escapeElementName (str) {
      var result = str.replace('[', '\\[').replace(']', '\\]')
      return (result)
    }

    // Adds ARIA attributes to control + associated content
    function initToggledContent () {
      var $control = $(this)
      var $content = getToggledContent($control)

      // Set aria-controls and defaults
      if ($content.length) {
        $control.attr('aria-controls', $content.attr('id'))
        $control.attr('aria-expanded', 'false')
        $content.attr('aria-hidden', 'true')
      }
    }

    // Return toggled content for control
    function getToggledContent ($control) {
      var id = $control.attr('aria-controls')

      // ARIA attributes aren't set before init
      if (!id) {
        id = $control.closest('label').data('target')
      }

      // Find show/hide content by id
      return $('#' + id)
    }

    // Show toggled content for control
    function showToggledContent ($control, $content) {
      // Show content
      if ($content.hasClass('js-hidden')) {
        $content.removeClass('js-hidden')
        $content.attr('aria-hidden', 'false')

        // If the controlling input, update aria-expanded
        if ($control.attr('aria-controls')) {
          $control.attr('aria-expanded', 'true')
        }
      }
    }

    // Hide toggled content for control
    function hideToggledContent ($control, $content) {
      $content = $content || getToggledContent($control)

      // Hide content
      if (!$content.hasClass('js-hidden')) {
        $content.addClass('js-hidden')
        $content.attr('aria-hidden', 'true')

        // If the controlling input, update aria-expanded
        if ($control.attr('aria-controls')) {
          $control.attr('aria-expanded', 'false')
        }
      }
    }

    // Handle radio show/hide
    function handleRadioContent ($control, $content) {
      // All radios in this group which control content
      var selector = selectors.radio + '[name=' + escapeElementName($control.attr('name')) + '][aria-controls]'
      var $radios = $control.closest('form').find(selector)

      // Hide content for radios in group
      $radios.each(function () {
        hideToggledContent($(this))
      })

      // Select content for this control
      if ($control.is('[aria-controls]')) {
        showToggledContent($control, $content)
      }
    }

    // Handle checkbox show/hide
    function handleCheckboxContent ($control, $content) {
      // Show checkbox content
      if ($control.is(':checked')) {
        showToggledContent($control, $content)
      } else { // Hide checkbox content
        hideToggledContent($control, $content)
      }
    }

    // Set up event handlers etc
    function init ($container, elementSelector, eventSelectors, handler) {
      $container = $container || $(document.body)

      // Handle control clicks
      function deferred () {
        var $control = $(this)
        handler($control, getToggledContent($control))
      }

      // Prepare ARIA attributes
      var $controls = $(elementSelector)
      $controls.each(initToggledContent)

      // Handle events
      $.each(eventSelectors, function (idx, eventSelector) {
        $container.on('click.' + selectors.namespace, eventSelector, deferred)
      })

      // Any already :checked on init?
      if ($controls.is(':checked')) {
        $controls.filter(':checked').each(deferred)
      }
    }

    // Get event selectors for all radio groups
    function getEventSelectorsForRadioGroups () {
      var radioGroups = []

      // Build an array of radio group selectors
      return $(selectors.radio).map(function () {
        var groupName = $(this).attr('name')

        if ($.inArray(groupName, radioGroups) === -1) {
          radioGroups.push(groupName)
          return 'input[type="radio"][name="' + $(this).attr('name') + '"]'
        }
        return null
      })
    }

    // Set up radio show/hide content for container
    self.showHideRadioToggledContent = function ($container) {
      init($container, selectors.radio, getEventSelectorsForRadioGroups(), handleRadioContent)
    }

    // Set up checkbox show/hide content for container
    self.showHideCheckboxToggledContent = function ($container) {
      init($container, selectors.checkbox, [selectors.checkbox], handleCheckboxContent)
    }

    // Remove event handlers
    self.destroy = function ($container) {
      $container = $container || $(document.body)
      $container.off('.' + selectors.namespace)
    }
  }

  ShowHideContent.prototype.init = function ($container) {
    this.showHideRadioToggledContent($container)
    this.showHideCheckboxToggledContent($container)
  }

  GOVUK.ShowHideContent = ShowHideContent
  global.GOVUK = GOVUK
})(window)
<commit_msg>Remove parenthesis from return expression<commit_after>;(function (global) {
  'use strict'

  var $ = global.jQuery
  var GOVUK = global.GOVUK || {}

  function ShowHideContent () {
    var self = this

    // Radio and Checkbox selectors
    var selectors = {
      namespace: 'ShowHideContent',
      radio: '.block-label[data-target] input[type="radio"]',
      checkbox: '.block-label[data-target] input[type="checkbox"]'
    }

    // Escape name attribute for use in DOM selector
    function escapeElementName (str) {
      var result = str.replace('[', '\\[').replace(']', '\\]')
      return result
    }

    // Adds ARIA attributes to control + associated content
    function initToggledContent () {
      var $control = $(this)
      var $content = getToggledContent($control)

      // Set aria-controls and defaults
      if ($content.length) {
        $control.attr('aria-controls', $content.attr('id'))
        $control.attr('aria-expanded', 'false')
        $content.attr('aria-hidden', 'true')
      }
    }

    // Return toggled content for control
    function getToggledContent ($control) {
      var id = $control.attr('aria-controls')

      // ARIA attributes aren't set before init
      if (!id) {
        id = $control.closest('label').data('target')
      }

      // Find show/hide content by id
      return $('#' + id)
    }

    // Show toggled content for control
    function showToggledContent ($control, $content) {
      // Show content
      if ($content.hasClass('js-hidden')) {
        $content.removeClass('js-hidden')
        $content.attr('aria-hidden', 'false')

        // If the controlling input, update aria-expanded
        if ($control.attr('aria-controls')) {
          $control.attr('aria-expanded', 'true')
        }
      }
    }

    // Hide toggled content for control
    function hideToggledContent ($control, $content) {
      $content = $content || getToggledContent($control)

      // Hide content
      if (!$content.hasClass('js-hidden')) {
        $content.addClass('js-hidden')
        $content.attr('aria-hidden', 'true')

        // If the controlling input, update aria-expanded
        if ($control.attr('aria-controls')) {
          $control.attr('aria-expanded', 'false')
        }
      }
    }

    // Handle radio show/hide
    function handleRadioContent ($control, $content) {
      // All radios in this group which control content
      var selector = selectors.radio + '[name=' + escapeElementName($control.attr('name')) + '][aria-controls]'
      var $radios = $control.closest('form').find(selector)

      // Hide content for radios in group
      $radios.each(function () {
        hideToggledContent($(this))
      })

      // Select content for this control
      if ($control.is('[aria-controls]')) {
        showToggledContent($control, $content)
      }
    }

    // Handle checkbox show/hide
    function handleCheckboxContent ($control, $content) {
      // Show checkbox content
      if ($control.is(':checked')) {
        showToggledContent($control, $content)
      } else { // Hide checkbox content
        hideToggledContent($control, $content)
      }
    }

    // Set up event handlers etc
    function init ($container, elementSelector, eventSelectors, handler) {
      $container = $container || $(document.body)

      // Handle control clicks
      function deferred () {
        var $control = $(this)
        handler($control, getToggledContent($control))
      }

      // Prepare ARIA attributes
      var $controls = $(elementSelector)
      $controls.each(initToggledContent)

      // Handle events
      $.each(eventSelectors, function (idx, eventSelector) {
        $container.on('click.' + selectors.namespace, eventSelector, deferred)
      })

      // Any already :checked on init?
      if ($controls.is(':checked')) {
        $controls.filter(':checked').each(deferred)
      }
    }

    // Get event selectors for all radio groups
    function getEventSelectorsForRadioGroups () {
      var radioGroups = []

      // Build an array of radio group selectors
      return $(selectors.radio).map(function () {
        var groupName = $(this).attr('name')

        if ($.inArray(groupName, radioGroups) === -1) {
          radioGroups.push(groupName)
          return 'input[type="radio"][name="' + $(this).attr('name') + '"]'
        }
        return null
      })
    }

    // Set up radio show/hide content for container
    self.showHideRadioToggledContent = function ($container) {
      init($container, selectors.radio, getEventSelectorsForRadioGroups(), handleRadioContent)
    }

    // Set up checkbox show/hide content for container
    self.showHideCheckboxToggledContent = function ($container) {
      init($container, selectors.checkbox, [selectors.checkbox], handleCheckboxContent)
    }

    // Remove event handlers
    self.destroy = function ($container) {
      $container = $container || $(document.body)
      $container.off('.' + selectors.namespace)
    }
  }

  ShowHideContent.prototype.init = function ($container) {
    this.showHideRadioToggledContent($container)
    this.showHideCheckboxToggledContent($container)
  }

  GOVUK.ShowHideContent = ShowHideContent
  global.GOVUK = GOVUK
})(window)
<|endoftext|>


<commit_before>var jsUrlsAllowed = false;
Blaze._allowJavascriptUrls = function () {
  jsUrlsAllowed = true;
};
Blaze._javascriptUrlsAllowed = function () {
  return jsUrlsAllowed;
};

// An AttributeHandler object is responsible for updating a particular attribute
// of a particular element.  AttributeHandler subclasses implement
// browser-specific logic for dealing with particular attributes across
// different browsers.
//
// To define a new type of AttributeHandler, use
// `var FooHandler = AttributeHandler.extend({ update: function ... })`
// where the `update` function takes arguments `(element, oldValue, value)`.
// The `element` argument is always the same between calls to `update` on
// the same instance.  `oldValue` and `value` are each either `null` or
// a Unicode string of the type that might be passed to the value argument
// of `setAttribute` (i.e. not an HTML string with character references).
// When an AttributeHandler is installed, an initial call to `update` is
// always made with `oldValue = null`.  The `update` method can access
// `this.name` if the AttributeHandler class is a generic one that applies
// to multiple attribute names.
//
// AttributeHandlers can store custom properties on `this`, as long as they
// don't use the names `element`, `name`, `value`, and `oldValue`.
//
// AttributeHandlers can't influence how attributes appear in rendered HTML,
// only how they are updated after materialization as DOM.

AttributeHandler = function (name, value) {
  this.name = name;
  this.value = value;
};

AttributeHandler.prototype.update = function (element, oldValue, value) {
  if (value === null) {
    if (oldValue !== null)
      element.removeAttribute(this.name);
  } else {
    element.setAttribute(this.name, value);
  }
};

AttributeHandler.extend = function (options) {
  var curType = this;
  var subType = function AttributeHandlerSubtype(/*arguments*/) {
    AttributeHandler.apply(this, arguments);
  };
  subType.prototype = new curType;
  subType.extend = curType.extend;
  if (options)
    _.extend(subType.prototype, options);
  return subType;
};

/// Apply the diff between the attributes of "oldValue" and "value" to "element."
//
// Each subclass must implement a parseValue method which takes a string
// as an input and returns a dict of attributes. The keys of the dict
// are unique identifiers (ie. css properties in the case of styles), and the
// values are the entire attribute which will be injected into the element.
//
// Extended below to support classes, SVG elements and styles.

var DiffingAttributeHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    if (!this.getCurrentValue || !this.setValue || !this.parseValue)
      throw new Error("Missing methods in subclass of 'DiffingAttributeHandler'");

    var oldAttrsMap = oldValue ? this.parseValue(oldValue) : {};
    var newAttrsMap = value ? this.parseValue(value) : {};

    // the current attributes on the element, which we will mutate.

    var attrString = this.getCurrentValue(element);
    var attrsMap = attrString ? this.parseValue(attrString) : {};

    _.each(_.keys(oldAttrsMap), function (t) {
      if (! (t in newAttrsMap))
        delete attrsMap[t];
    });

    _.each(_.keys(newAttrsMap), function (t) {
      attrsMap[t] = newAttrsMap[t];
    });

    this.setValue(element, _.values(attrsMap).join(' '));
  }
});

var ClassHandler = DiffingAttributeHandler.extend({
  // @param rawValue {String}
  getCurrentValue: function (element) {
    return element.className;
  },
  setValue: function (element, className) {
    element.className = className;
  },
  parseValue: function (attrString) {
    var tokens = {};

    _.each(attrString.split(' '), function(token) {
      if (token)
        tokens[token] = token;
    });
    return tokens;
  }
});

var SVGClassHandler = ClassHandler.extend({
  getCurrentValue: function (element) {
    return element.className.baseVal;
  },
  setValue: function (element, className) {
    element.setAttribute('class', className);
  }
});

var StyleHandler = DiffingAttributeHandler.extend({
  getCurrentValue: function (element) {
    return element.getAttribute('style');
  },
  setValue: function (element, style) {
    if (style === '') {
      element.removeAttribute('style');
    } else {
      element.setAttribute('style', style);
    }
  },

  // Parse a string to produce a map from property to attribute string.
  //
  // Example:
  // "color:red; foo:12px" produces a token {color: "color:red", foo:"foo:12px"}
  parseValue: function (attrString) {
    var tokens = {};

    // Regex for parsing a css attribute declaration, taken from css-parse:
    // https://github.com/reworkcss/css-parse/blob/7cef3658d0bba872cde05a85339034b187cb3397/index.js#L219
    var regex = /(\*?[-#\/\*\\\w]+(?:\[[0-9a-z_-]+\])?)\s*:\s*(?:\'(?:\\\'|.)*?\'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+[;\s]*/g;
    var match = regex.exec(attrString);
    while (match) {
      // match[0] = entire matching string
      // match[1] = css property
      // Prefix the token to prevent conflicts with existing properties.

      // XXX No `String.trim` on Safari 4. Swap out $.trim if we want to
      // remove strong dep on jquery.
      tokens[' ' + match[1]] = match[0].trim ?
        match[0].trim() : $.trim(match[0]);

      match = regex.exec(attrString);
    }

    return tokens;
  }
});

var BooleanHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    var name = this.name;
    if (value == null) {
      if (oldValue != null)
        element[name] = false;
    } else {
      element[name] = true;
    }
  }
});

var ValueHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    element.value = value;
  }
});

// attributes of the type 'xlink:something' should be set using
// the correct namespace in order to work
var XlinkHandler = AttributeHandler.extend({
  update: function(element, oldValue, value) {
    var NS = 'http://www.w3.org/1999/xlink';
    if (value === null) {
      if (oldValue !== null)
        element.removeAttributeNS(NS, this.name);
    } else {
      element.setAttributeNS(NS, this.name, this.value);
    }
  }
});

// cross-browser version of `instanceof SVGElement`
var isSVGElement = function (elem) {
  return 'ownerSVGElement' in elem;
};

var isUrlAttribute = function (tagName, attrName) {
  // Compiled from http://www.w3.org/TR/REC-html40/index/attributes.html
  // and
  // http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1
  var urlAttrs = {
    FORM: ['action'],
    BODY: ['background'],
    BLOCKQUOTE: ['cite'],
    Q: ['cite'],
    DEL: ['cite'],
    INS: ['cite'],
    OBJECT: ['classid', 'codebase', 'data', 'usemap'],
    APPLET: ['codebase'],
    A: ['href'],
    AREA: ['href'],
    LINK: ['href'],
    BASE: ['href'],
    IMG: ['longdesc', 'src', 'usemap'],
    FRAME: ['longdesc', 'src'],
    IFRAME: ['longdesc', 'src'],
    HEAD: ['profile'],
    SCRIPT: ['src'],
    INPUT: ['src', 'usemap', 'formaction'],
    BUTTON: ['formaction'],
    BASE: ['href'],
    MENUITEM: ['icon'],
    HTML: ['manifest'],
    VIDEO: ['poster']
  };

  if (attrName === 'itemid') {
    return true;
  }

  var urlAttrNames = urlAttrs[tagName] || [];
  return _.contains(urlAttrNames, attrName);
};

// To get the protocol for a URL, we let the browser normalize it for
// us, by setting it as the href for an anchor tag and then reading out
// the 'protocol' property.
if (Meteor.isClient) {
  var anchorForNormalization = document.createElement('A');
}

var getUrlProtocol = function (url) {
  if (Meteor.isClient) {
    anchorForNormalization.href = url;
    return (anchorForNormalization.protocol || "").toLowerCase();
  } else {
    throw new Error('getUrlProtocol not implemented on the server');
  }
};

// UrlHandler is an attribute handler for all HTML attributes that take
// URL values. It disallows javascript: URLs, unless
// Blaze._allowJavascriptUrls() has been called. To detect javascript:
// urls, we set the attribute on a dummy anchor element and then read
// out the 'protocol' property of the attribute.
var origUpdate = AttributeHandler.prototype.update;
var UrlHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    var self = this;
    var args = arguments;

    if (Blaze._javascriptUrlsAllowed()) {
      origUpdate.apply(self, args);
    } else {
      var isJavascriptProtocol = (getUrlProtocol(value) === "javascript:");
      if (isJavascriptProtocol) {
        var blazeSymbol = ((typeof UI !== 'undefined') && UI === Blaze) ?
              'UI' : 'Blaze';
        Meteor._debug("URLs that use the 'javascript:' protocol are not " +
                      "allowed in URL attribute values. " +
                      "Call " + blazeSymbol + "._allowJavascriptUrls() " +
                      "to enable them.");
        origUpdate.apply(self, [element, oldValue, null]);
      } else {
        origUpdate.apply(self, args);
      }
    }
  }
});

// XXX make it possible for users to register attribute handlers!
makeAttributeHandler = function (elem, name, value) {
  // generally, use setAttribute but certain attributes need to be set
  // by directly setting a JavaScript property on the DOM element.
  if (name === 'class') {
    if (isSVGElement(elem)) {
      return new SVGClassHandler(name, value);
    } else {
      return new ClassHandler(name, value);
    }
  } else if (name === 'style') {
    return new StyleHandler(name, value);
  } else if ((elem.tagName === 'OPTION' && name === 'selected') ||
             (elem.tagName === 'INPUT' && name === 'checked')) {
    return new BooleanHandler(name, value);
  } else if ((elem.tagName === 'TEXTAREA' || elem.tagName === 'INPUT')
             && name === 'value') {
    // internally, TEXTAREAs tracks their value in the 'value'
    // attribute just like INPUTs.
    return new ValueHandler(name, value);
  } else if (name.substring(0,6) === 'xlink:') {
    return new XlinkHandler(name.substring(6), value);
  } else if (isUrlAttribute(elem.tagName, name)) {
    return new UrlHandler(name, value);
  } else {
    return new AttributeHandler(name, value);
  }

  // XXX will need one for 'style' on IE, though modern browsers
  // seem to handle setAttribute ok.
};

ElementAttributesUpdater = function (elem) {
  this.elem = elem;
  this.handlers = {};
};

// Update attributes on `elem` to the dictionary `attrs`, whose
// values are strings.
ElementAttributesUpdater.prototype.update = function(newAttrs) {
  var elem = this.elem;
  var handlers = this.handlers;

  for (var k in handlers) {
    if (! _.has(newAttrs, k)) {
      // remove attributes (and handlers) for attribute names
      // that don't exist as keys of `newAttrs` and so won't
      // be visited when traversing it.  (Attributes that
      // exist in the `newAttrs` object but are `null`
      // are handled later.)
      var handler = handlers[k];
      var oldValue = handler.value;
      handler.value = null;
      handler.update(elem, oldValue, null);
      delete handlers[k];
    }
  }

  for (var k in newAttrs) {
    var handler = null;
    var oldValue;
    var value = newAttrs[k];
    if (! _.has(handlers, k)) {
      if (value !== null) {
        // make new handler
        handler = makeAttributeHandler(elem, k, value);
        handlers[k] = handler;
        oldValue = null;
      }
    } else {
      handler = handlers[k];
      oldValue = handler.value;
    }
    if (oldValue !== value) {
      handler.value = value;
      handler.update(elem, oldValue, value);
      if (value === null)
        delete handlers[k];
    }
  }
};
<commit_msg>Expose AttributeHandler (privately)<commit_after>var jsUrlsAllowed = false;
Blaze._allowJavascriptUrls = function () {
  jsUrlsAllowed = true;
};
Blaze._javascriptUrlsAllowed = function () {
  return jsUrlsAllowed;
};

// An AttributeHandler object is responsible for updating a particular attribute
// of a particular element.  AttributeHandler subclasses implement
// browser-specific logic for dealing with particular attributes across
// different browsers.
//
// To define a new type of AttributeHandler, use
// `var FooHandler = AttributeHandler.extend({ update: function ... })`
// where the `update` function takes arguments `(element, oldValue, value)`.
// The `element` argument is always the same between calls to `update` on
// the same instance.  `oldValue` and `value` are each either `null` or
// a Unicode string of the type that might be passed to the value argument
// of `setAttribute` (i.e. not an HTML string with character references).
// When an AttributeHandler is installed, an initial call to `update` is
// always made with `oldValue = null`.  The `update` method can access
// `this.name` if the AttributeHandler class is a generic one that applies
// to multiple attribute names.
//
// AttributeHandlers can store custom properties on `this`, as long as they
// don't use the names `element`, `name`, `value`, and `oldValue`.
//
// AttributeHandlers can't influence how attributes appear in rendered HTML,
// only how they are updated after materialization as DOM.

AttributeHandler = function (name, value) {
  this.name = name;
  this.value = value;
};
Blaze._AttributeHandler = AttributeHandler;

AttributeHandler.prototype.update = function (element, oldValue, value) {
  if (value === null) {
    if (oldValue !== null)
      element.removeAttribute(this.name);
  } else {
    element.setAttribute(this.name, value);
  }
};

AttributeHandler.extend = function (options) {
  var curType = this;
  var subType = function AttributeHandlerSubtype(/*arguments*/) {
    AttributeHandler.apply(this, arguments);
  };
  subType.prototype = new curType;
  subType.extend = curType.extend;
  if (options)
    _.extend(subType.prototype, options);
  return subType;
};

/// Apply the diff between the attributes of "oldValue" and "value" to "element."
//
// Each subclass must implement a parseValue method which takes a string
// as an input and returns a dict of attributes. The keys of the dict
// are unique identifiers (ie. css properties in the case of styles), and the
// values are the entire attribute which will be injected into the element.
//
// Extended below to support classes, SVG elements and styles.

var DiffingAttributeHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    if (!this.getCurrentValue || !this.setValue || !this.parseValue)
      throw new Error("Missing methods in subclass of 'DiffingAttributeHandler'");

    var oldAttrsMap = oldValue ? this.parseValue(oldValue) : {};
    var newAttrsMap = value ? this.parseValue(value) : {};

    // the current attributes on the element, which we will mutate.

    var attrString = this.getCurrentValue(element);
    var attrsMap = attrString ? this.parseValue(attrString) : {};

    _.each(_.keys(oldAttrsMap), function (t) {
      if (! (t in newAttrsMap))
        delete attrsMap[t];
    });

    _.each(_.keys(newAttrsMap), function (t) {
      attrsMap[t] = newAttrsMap[t];
    });

    this.setValue(element, _.values(attrsMap).join(' '));
  }
});

var ClassHandler = DiffingAttributeHandler.extend({
  // @param rawValue {String}
  getCurrentValue: function (element) {
    return element.className;
  },
  setValue: function (element, className) {
    element.className = className;
  },
  parseValue: function (attrString) {
    var tokens = {};

    _.each(attrString.split(' '), function(token) {
      if (token)
        tokens[token] = token;
    });
    return tokens;
  }
});

var SVGClassHandler = ClassHandler.extend({
  getCurrentValue: function (element) {
    return element.className.baseVal;
  },
  setValue: function (element, className) {
    element.setAttribute('class', className);
  }
});

var StyleHandler = DiffingAttributeHandler.extend({
  getCurrentValue: function (element) {
    return element.getAttribute('style');
  },
  setValue: function (element, style) {
    if (style === '') {
      element.removeAttribute('style');
    } else {
      element.setAttribute('style', style);
    }
  },

  // Parse a string to produce a map from property to attribute string.
  //
  // Example:
  // "color:red; foo:12px" produces a token {color: "color:red", foo:"foo:12px"}
  parseValue: function (attrString) {
    var tokens = {};

    // Regex for parsing a css attribute declaration, taken from css-parse:
    // https://github.com/reworkcss/css-parse/blob/7cef3658d0bba872cde05a85339034b187cb3397/index.js#L219
    var regex = /(\*?[-#\/\*\\\w]+(?:\[[0-9a-z_-]+\])?)\s*:\s*(?:\'(?:\\\'|.)*?\'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+[;\s]*/g;
    var match = regex.exec(attrString);
    while (match) {
      // match[0] = entire matching string
      // match[1] = css property
      // Prefix the token to prevent conflicts with existing properties.

      // XXX No `String.trim` on Safari 4. Swap out $.trim if we want to
      // remove strong dep on jquery.
      tokens[' ' + match[1]] = match[0].trim ?
        match[0].trim() : $.trim(match[0]);

      match = regex.exec(attrString);
    }

    return tokens;
  }
});

var BooleanHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    var name = this.name;
    if (value == null) {
      if (oldValue != null)
        element[name] = false;
    } else {
      element[name] = true;
    }
  }
});

var ValueHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    element.value = value;
  }
});

// attributes of the type 'xlink:something' should be set using
// the correct namespace in order to work
var XlinkHandler = AttributeHandler.extend({
  update: function(element, oldValue, value) {
    var NS = 'http://www.w3.org/1999/xlink';
    if (value === null) {
      if (oldValue !== null)
        element.removeAttributeNS(NS, this.name);
    } else {
      element.setAttributeNS(NS, this.name, this.value);
    }
  }
});

// cross-browser version of `instanceof SVGElement`
var isSVGElement = function (elem) {
  return 'ownerSVGElement' in elem;
};

var isUrlAttribute = function (tagName, attrName) {
  // Compiled from http://www.w3.org/TR/REC-html40/index/attributes.html
  // and
  // http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1
  var urlAttrs = {
    FORM: ['action'],
    BODY: ['background'],
    BLOCKQUOTE: ['cite'],
    Q: ['cite'],
    DEL: ['cite'],
    INS: ['cite'],
    OBJECT: ['classid', 'codebase', 'data', 'usemap'],
    APPLET: ['codebase'],
    A: ['href'],
    AREA: ['href'],
    LINK: ['href'],
    BASE: ['href'],
    IMG: ['longdesc', 'src', 'usemap'],
    FRAME: ['longdesc', 'src'],
    IFRAME: ['longdesc', 'src'],
    HEAD: ['profile'],
    SCRIPT: ['src'],
    INPUT: ['src', 'usemap', 'formaction'],
    BUTTON: ['formaction'],
    BASE: ['href'],
    MENUITEM: ['icon'],
    HTML: ['manifest'],
    VIDEO: ['poster']
  };

  if (attrName === 'itemid') {
    return true;
  }

  var urlAttrNames = urlAttrs[tagName] || [];
  return _.contains(urlAttrNames, attrName);
};

// To get the protocol for a URL, we let the browser normalize it for
// us, by setting it as the href for an anchor tag and then reading out
// the 'protocol' property.
if (Meteor.isClient) {
  var anchorForNormalization = document.createElement('A');
}

var getUrlProtocol = function (url) {
  if (Meteor.isClient) {
    anchorForNormalization.href = url;
    return (anchorForNormalization.protocol || "").toLowerCase();
  } else {
    throw new Error('getUrlProtocol not implemented on the server');
  }
};

// UrlHandler is an attribute handler for all HTML attributes that take
// URL values. It disallows javascript: URLs, unless
// Blaze._allowJavascriptUrls() has been called. To detect javascript:
// urls, we set the attribute on a dummy anchor element and then read
// out the 'protocol' property of the attribute.
var origUpdate = AttributeHandler.prototype.update;
var UrlHandler = AttributeHandler.extend({
  update: function (element, oldValue, value) {
    var self = this;
    var args = arguments;

    if (Blaze._javascriptUrlsAllowed()) {
      origUpdate.apply(self, args);
    } else {
      var isJavascriptProtocol = (getUrlProtocol(value) === "javascript:");
      if (isJavascriptProtocol) {
        var blazeSymbol = ((typeof UI !== 'undefined') && UI === Blaze) ?
              'UI' : 'Blaze';
        Meteor._debug("URLs that use the 'javascript:' protocol are not " +
                      "allowed in URL attribute values. " +
                      "Call " + blazeSymbol + "._allowJavascriptUrls() " +
                      "to enable them.");
        origUpdate.apply(self, [element, oldValue, null]);
      } else {
        origUpdate.apply(self, args);
      }
    }
  }
});

// XXX make it possible for users to register attribute handlers!
makeAttributeHandler = function (elem, name, value) {
  // generally, use setAttribute but certain attributes need to be set
  // by directly setting a JavaScript property on the DOM element.
  if (name === 'class') {
    if (isSVGElement(elem)) {
      return new SVGClassHandler(name, value);
    } else {
      return new ClassHandler(name, value);
    }
  } else if (name === 'style') {
    return new StyleHandler(name, value);
  } else if ((elem.tagName === 'OPTION' && name === 'selected') ||
             (elem.tagName === 'INPUT' && name === 'checked')) {
    return new BooleanHandler(name, value);
  } else if ((elem.tagName === 'TEXTAREA' || elem.tagName === 'INPUT')
             && name === 'value') {
    // internally, TEXTAREAs tracks their value in the 'value'
    // attribute just like INPUTs.
    return new ValueHandler(name, value);
  } else if (name.substring(0,6) === 'xlink:') {
    return new XlinkHandler(name.substring(6), value);
  } else if (isUrlAttribute(elem.tagName, name)) {
    return new UrlHandler(name, value);
  } else {
    return new AttributeHandler(name, value);
  }

  // XXX will need one for 'style' on IE, though modern browsers
  // seem to handle setAttribute ok.
};

ElementAttributesUpdater = function (elem) {
  this.elem = elem;
  this.handlers = {};
};

// Update attributes on `elem` to the dictionary `attrs`, whose
// values are strings.
ElementAttributesUpdater.prototype.update = function(newAttrs) {
  var elem = this.elem;
  var handlers = this.handlers;

  for (var k in handlers) {
    if (! _.has(newAttrs, k)) {
      // remove attributes (and handlers) for attribute names
      // that don't exist as keys of `newAttrs` and so won't
      // be visited when traversing it.  (Attributes that
      // exist in the `newAttrs` object but are `null`
      // are handled later.)
      var handler = handlers[k];
      var oldValue = handler.value;
      handler.value = null;
      handler.update(elem, oldValue, null);
      delete handlers[k];
    }
  }

  for (var k in newAttrs) {
    var handler = null;
    var oldValue;
    var value = newAttrs[k];
    if (! _.has(handlers, k)) {
      if (value !== null) {
        // make new handler
        handler = makeAttributeHandler(elem, k, value);
        handlers[k] = handler;
        oldValue = null;
      }
    } else {
      handler = handlers[k];
      oldValue = handler.value;
    }
    if (oldValue !== value) {
      handler.value = value;
      handler.update(elem, oldValue, value);
      if (value === null)
        delete handlers[k];
    }
  }
};
<|endoftext|>


<commit_before>/*
1000 => Debe especificarse un atributo "action" con valor "set" o "get"
1001 => Debe de llamarse a call con un objeto consulta
1002 => debe de especificarse un action en el objeto consulta
1003 => debe de especificarse un nombre de widget en el objeto consulta
*/

/*
parametros => (
	action => get/set,
	widget => (
		'widget1' => (
			'variable1'
		)
	)
)
*/

API = (function(){
	var precall = function(parametros, callback){

		var comando = {
			'action':parametros['action'],
			'widgets':{}
		};
		comando['widgets'][parametros['widget']] = parametros['variables'];

		call(comando, callback);
	}

	var call = function(parametros, callback){
		if(parametros){
			if(typeof parametros["action"] === "string"){
				if(typeof parametros["widgets"] === "object"){
					// Una variable
					get_o_set(parametros["action"], callback, parametros["widgets"]);
				}
				else{
					callback(fail(1003));
				}
			}
			else{
				callback(fail(1002));
			}
		}
		else{
			callback(fail(1001));
		}
	}

	var get_o_set = function(modo, callback, widgets){
		for(var widget in widgets){
			if(typeof widgets[widget] === 'string'){
				widgets[widget] = [widgets[widget]];
			}
		}
		switch(modo){
			case 'get':
				for(var widget in widgets){
					agregaAConsultaGet(widget, widgets[widget]);
				}
				callbacksConsultaGet.push({"callback":callback,"widgets":widgets});
				clearTimeout(timeoutGet);
				timeoutGet = setTimeout(procesaGet, 100);
			break;
			case 'set':
				for(var widget in widgets){
					agregaAConsultaSet(widget, widgets[widget]);
				}
				callbacksConsultaSet.push({"callback":callback,"widgets":widgets});
				clearTimeout(timeoutSet);
				timeoutSet = setTimeout(procesaSet, 100);
			break;
			default:
				callback(fail(1000));
			break;
		}
	}

	// OK
	// string, []
	var agregaAConsultaGet = function(widget, array_variables){
		if(proximaConsultaGet[widget] === undefined){
			proximaConsultaGet[widget] = {};
		}
		for(var i in array_variables){
			proximaConsultaGet[widget][array_variables[i]] = null;
		}
	}

	// OK
	// string, [], []
	var agregaAConsultaSet = function(widget, array_variables){
		if(proximaConsultaSet[widget] === undefined){
			proximaConsultaSet[widget] = {};
		}
		for(var i in array_variables){
			proximaConsultaSet[widget][i] = array_variables[i];
		}
	}

	var timeoutGet = 0;
	var timeoutSet = 0;

	var callbacksConsultaGet = [];
	var callbacksConsultaSet = [];

	var proximaConsultaGet = {};
	var proximaConsultaSet = {};

	var fail = function(n){
		return {'response':'FAIL',"content":n};
	}

	var procesa = function(action, proximaConsulta, callbacksConsulta){
		var req = new XMLHttpRequest();
		req.open('POST', 'api.php', true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.onreadystatechange = function(aEvt){
			if(req.readyState == 4){
				if(req.status == 200){
					//console.log(req.responseText);
					var respuesta = JSON.parse(req.responseText);

					if(action === 'set'){
						var a = 'a';
					}

					// Recorrer los callback y generar respuesta
					if(respuesta['response']==='OK'){
						for(var i in callbacksConsulta){

							var obj = {};
							var widget = '';

							// Por cada widget pedido
							for(widget in callbacksConsulta[i]['widgets']){
								// Si está recibido
								if(typeof respuesta['content'][widget] !== 'undefined'){
									obj[widget] = {};
									switch(action){
										case 'get':
											for(var j in callbacksConsulta[i]['widgets'][widget]){
												var variable = callbacksConsulta[i]['widgets'][widget][j];
												// Si se pidió la variable
												if(typeof respuesta['content'][widget][variable] !== 'undefined'){
													obj[widget][variable] = respuesta['content'][widget][variable];
												}
											}
										break;
										case 'set':
											for(var variable in callbacksConsulta[i]['widgets'][widget]){
												// Si se pidió la variable
												if(typeof respuesta['content'][widget][variable] !== 'undefined'){
													obj[widget][variable] = respuesta['content'][widget][variable];
												}
											}
										break;
									}
								}
							}
							callbacksConsulta[i]['callback'](obj[widget]);
						}
					}
					else{
						for(var i in callbacksConsulta){
							callbacksConsulta[i]['callback'](respuesta);
						}
					}
				}
				else{
					console.log("Error loading page");
				}
			}
		};
		var data = 'action='+action+'&data='+encodeURIComponent(JSON.stringify(proximaConsulta));
		req.send(data);
	}

	var procesaGet = function(){
		procesa('get', proximaConsultaGet, callbacksConsultaGet);
		proximaConsultaGet = {};
		callbacksConsultaGet = [];
	}

	var procesaSet = function(){
		procesa('set', proximaConsultaSet, callbacksConsultaSet);
		proximaConsultaSet = {};
		callbacksConsultaSet = [];
	}

	var getUrl = function(widget, filename){
		return 'widgetfile.php?widgetID='+widget+'&api=1&name='+escape(filename);
	}

	return {
		"call":precall,
		"url":getUrl
	};
})();<commit_msg>API js fix and annotations<commit_after>/*
1000 => Debe especificarse un atributo "action" con valor "set" o "get"
1001 => Debe de llamarse a call con un objeto consulta
1002 => debe de especificarse un action en el objeto consulta
1003 => debe de especificarse un nombre de widget en el objeto consulta
*/

/*
parametros => (
	action => get/set,
	widget => (
		'widget1' => (
			'variable1'
		)
	)
)
*/

API = (function(){
	var precall = function(parametros, callback){

		var comando = {
			'action':parametros['action'],
			'widgets':{}
		};
		comando['widgets'][parametros['widget']] = parametros['variables'];

		call(comando, callback);
	}

	var call = function(parametros, callback){
		if(parametros){
			if(typeof parametros["action"] === "string"){
				if(typeof parametros["widgets"] === "object"){
					// Una variable
					get_o_set(parametros["action"], callback, parametros["widgets"]);
				}
				else{
					callback(fail(1003));
				}
			}
			else{
				callback(fail(1002));
			}
		}
		else{
			callback(fail(1001));
		}
	}

	var get_o_set = function(modo, callback, widgets){
		for(var widget in widgets){
			if(typeof widgets[widget] === 'string'){
				widgets[widget] = [widgets[widget]];
			}
		}
		switch(modo){
			case 'get':
				for(var widget in widgets){
					agregaAConsultaGet(widget, widgets[widget]);
				}
				callbacksConsultaGet.push({"callback":callback,"widgets":widgets});
				clearTimeout(timeoutGet);
				timeoutGet = setTimeout(procesaGet, 100);
			break;
			case 'set':
				for(var widget in widgets){
					agregaAConsultaSet(widget, widgets[widget]);
				}
				callbacksConsultaSet.push({"callback":callback,"widgets":widgets});
				clearTimeout(timeoutSet);
				timeoutSet = setTimeout(procesaSet, 100);
			break;
			default:
				callback(fail(1000));
			break;
		}
	}

	// OK
	// string, []
	var agregaAConsultaGet = function(widget, array_variables){
		if(proximaConsultaGet[widget] === undefined){
			proximaConsultaGet[widget] = {};
		}
		for(var i in array_variables){
			proximaConsultaGet[widget][array_variables[i]] = null;
		}
	}

	// OK
	// string, [], []
	var agregaAConsultaSet = function(widget, array_variables){
		if(proximaConsultaSet[widget] === undefined){
			proximaConsultaSet[widget] = {};
		}
		for(var i in array_variables){
			proximaConsultaSet[widget][i] = array_variables[i];
		}
	}

	var timeoutGet = 0;
	var timeoutSet = 0;

	var callbacksConsultaGet = [];
	var callbacksConsultaSet = [];

	var proximaConsultaGet = {};
	var proximaConsultaSet = {};

	var fail = function(n){
		return {'response':'FAIL',"content":n};
	}

	var procesa = function(action, proximaConsulta, callbacksConsulta){
		var req = new XMLHttpRequest();
		req.open('POST', 'api.php', true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.onreadystatechange = function(aEvt){
			if(req.readyState == 4){
				if(req.status == 200){
					//console.log(req.responseText);
					var respuesta = JSON.parse(req.responseText);

					if(action === 'set'){
						var a = 'a';
					}

					// Recorrer los callback y generar respuesta
					if(respuesta['response']==='OK'){
						for(var i in callbacksConsulta){

							var obj = {};
							var widget = '';

							// Por cada widget pedido
							for(widget in callbacksConsulta[i]['widgets']){
								// Si está recibido
								if(typeof respuesta['content'][widget] !== 'undefined'){
									obj[widget] = {};
									switch(action){
										case 'get':
											// Array pattern ['var1', 'var2']
											for(var j in callbacksConsulta[i]['widgets'][widget]){
												var variable = callbacksConsulta[i]['widgets'][widget][j];
												// Si se pidió la variable
												if(typeof respuesta['content'][widget][variable] !== 'undefined'){
													obj[widget][variable] = respuesta['content'][widget][variable];
												}
											}
										break;
										case 'set':
											// Object pattern {'var1':'', 'var2':''}
											for(var variable in callbacksConsulta[i]['widgets'][widget]){
												// Si se pidió la variable
												if(typeof respuesta['content'][widget][variable] !== 'undefined'){
													obj[widget][variable] = respuesta['content'][widget][variable];
												}
											}
										break;
									}
								}
								callbacksConsulta[i]['callback'](obj[widget]);
							}
						}
					}
					else{
						for(var i in callbacksConsulta){
							callbacksConsulta[i]['callback'](respuesta);
						}
					}
				}
				else{
					console.log("Error loading page");
				}
			}
		};
		var data = 'action='+action+'&data='+encodeURIComponent(JSON.stringify(proximaConsulta));
		req.send(data);
	}

	var procesaGet = function(){
		procesa('get', proximaConsultaGet, callbacksConsultaGet);
		proximaConsultaGet = {};
		callbacksConsultaGet = [];
	}

	var procesaSet = function(){
		procesa('set', proximaConsultaSet, callbacksConsultaSet);
		proximaConsultaSet = {};
		callbacksConsultaSet = [];
	}

	var getUrl = function(widget, filename){
		return 'widgetfile.php?widgetID='+widget+'&api=1&name='+escape(filename);
	}

	return {
		"call":precall,
		"url":getUrl
	};
})();<|endoftext|>


<commit_before>'use strict'
var fs = require('graceful-fs')
var path = require('path')
var zlib = require('zlib')

var log = require('npmlog')
var realizePackageSpecifier = require('realize-package-specifier')
var tar = require('tar')
var once = require('once')
var semver = require('semver')
var readPackageTree = require('read-package-tree')
var iferr = require('iferr')
var rimraf = require('rimraf')
var clone = require('lodash.clonedeep')
var validate = require('aproba')

var npm = require('./npm.js')
var mapToRegistry = require('./utils/map-to-registry.js')
var cache = require('./cache.js')
var cachedPackageRoot = require('./cache/cached-package-root.js')
var tempFilename = require('./utils/temp-filename.js')
var getCacheStat = require('./cache/get-stat.js')
var unpack = require('./utils/tar.js').unpack
var pulseTillDone = require('./utils/pulse-till-done.js')

function andLogAndFinish (spec, tracker, done) {
  validate('SF', [spec, done])
  return function (er, pkg) {
    validate('EO', arguments)
    if (er) {
      log.silly('fetchPackageMetaData', 'error for ' + spec, er)
      if (tracker) tracker.finish()
    }
    return done(er, pkg)
  }
}

module.exports = function fetchPackageMetadata (spec, where, tracker, done) {
  if (!done) {
    done = tracker || where
    tracker = null
    if (done === where) where = null
  }
  if (typeof spec === 'object') {
    var dep = spec
    spec = dep.raw
  }
  var logAndFinish = andLogAndFinish(spec, tracker, done)
  if (!dep) {
    log.silly('fetchPackageMetaData', spec)
    return realizePackageSpecifier(spec, where, iferr(logAndFinish, function (dep) {
      fetchPackageMetadata(dep, where, tracker, done)
    }))
  }
  if (dep.type === 'version' || dep.type === 'range' || dep.type === 'tag') {
    fetchNamedPackageData(dep, addRequestedAndFinish)
  } else {
    fetchOtherPackageData(spec, dep, where, addRequestedAndFinish)
  }
  function addRequestedAndFinish (er, pkg) {
    validate('EO', arguments)
    if (pkg) {
      pkg._requested = dep
      pkg._spec = spec
      pkg._where = where
      if (!pkg._args) pkg._args = []
      pkg._args.push([pkg._spec, pkg._where])
    }
    logAndFinish(er, pkg)
  }
}

function fetchOtherPackageData (spec, dep, where, next) {
  validate('SOSF', arguments)
  log.silly('fetchOtherPackageData', spec)
  cache.add(spec, null, where, false, iferr(next, function (pkg) {
    var result = clone(pkg)
    result._inCache = true
    next(null, result)
  }))
}

var regCache = {}

function fetchNamedPackageData (dep, next) {
  validate('OF', arguments)
  log.silly('fetchNamedPackageData', dep.name || dep.rawSpec)
  mapToRegistry(dep.name || dep.rawSpec, npm.config, iferr(next, function (url, auth) {
    if (regCache[url]) {
      pickVersionFromRegistryDocument(clone(regCache[url]))
    } else {
      npm.registry.get(url, {auth: auth}, pulseTillDone('fetchMetadata', iferr(next, pickVersionFromRegistryDocument)))
    }
    function returnAndAddMetadata (pkg) {
      delete pkg._from
      delete pkg._resolved
      delete pkg._shasum
      next(null, pkg)
    }
    function pickVersionFromRegistryDocument (pkg) {
      if (!regCache[url]) regCache[url] = pkg
      var versions = Object.keys(pkg.versions).sort(semver.rcompare)

      if (dep.type === 'tag') {
        var tagVersion = pkg['dist-tags'][dep.spec]
        if (pkg.versions[tagVersion]) return returnAndAddMetadata(pkg.versions[tagVersion])
      } else {
        var latestVersion = pkg['dist-tags'].latest || versions[0]

        // Find the the most recent version less than or equal
        // to latestVersion that satisfies our spec
        for (var ii = 0; ii < versions.length; ++ii) {
          if (semver.gt(versions[ii], latestVersion)) continue
          if (semver.satisfies(versions[ii], dep.spec)) {
            return returnAndAddMetadata(pkg.versions[versions[ii]])
          }
        }

        // Failing that, try finding the most recent version that matches
        // our spec
        for (var jj = 0; jj < versions.length; ++jj) {
          if (semver.satisfies(versions[jj], dep.spec)) {
            return returnAndAddMetadata(pkg.versions[versions[jj]])
          }
        }
      }

      // And failing that, we error out
      var targets = versions.length
                  ? 'Valid install targets:\n' + JSON.stringify(versions) + '\n'
                  : 'No valid targets found.'
      var er = new Error('No compatible version found: ' +
                         dep.rawSpec + '\n' + targets)
      return next(er)
    }
  }))
}

function retryWithCached (pkg, asserter, next) {
  if (!pkg._inCache) {
    cache.add(pkg._spec, null, pkg._where, false, iferr(next, function (newpkg) {
      Object.keys(newpkg).forEach(function (key) {
        if (key[0] !== '_') return
        pkg[key] = newpkg[key]
      })
      pkg._inCache = true
      return asserter(pkg, next)
    }))
  }
  return !pkg._inCache
}

module.exports.addShrinkwrap = function addShrinkwrap (pkg, next) {
  validate('OF', arguments)
  if (pkg._shrinkwrap !== undefined) return next(null, pkg)
  if (retryWithCached(pkg, addShrinkwrap, next)) return
  pkg._shrinkwrap = null
  // FIXME: cache the shrinkwrap directly
  var pkgname = pkg.name
  var ver = pkg.version
  var tarball = path.join(cachedPackageRoot({name: pkgname, version: ver}), 'package.tgz')
  untarStream(tarball, function (er, untar) {
    if (er) {
      if (er.code === 'ENOTTARBALL') {
        pkg._shrinkwrap = null
        return next()
      } else {
        return next(er)
      }
    }
    if (er) return next(er)
    var foundShrinkwrap = false
    log.silly('addShrinkwrap', 'Adding shrinkwrap to ' + pkgname)
    untar.on('entry', function (entry) {
      if (!/^(?:[^\/]+[\/])npm-shrinkwrap.json$/.test(entry.path)) return
      log.silly('addShrinkwrap', 'Found shrinkwrap at ' + entry.path)
      foundShrinkwrap = true
      var shrinkwrap = ''
      entry.on('data', function (chunk) {
        shrinkwrap += chunk
      })
      entry.on('end', function () {
        untar.close()
        log.silly('addShrinkwrap', 'Done reading shrinkwrap')
        try {
          pkg._shrinkwrap = JSON.parse(shrinkwrap)
        } catch (ex) {
          var er = new Error('Error parsing ' + pkgname + '@' + ver + "'s npm-shrinkwrap.json: " + ex.message)
          er.type = 'ESHRINKWRAP'
          return next(er)
        }
        next(null, pkg)
      })
      entry.resume()
    })
    untar.on('end', function () {
      if (!foundShrinkwrap) {
        pkg._shrinkwrap = null
        next(null, pkg)
      }
    })
  })
}

module.exports.addBundled = function addBundled (pkg, next) {
  validate('OF', arguments)
  if (pkg._bundled !== undefined) return next(null, pkg)
  if (!pkg.bundleDependencies) return next(null, pkg)
  if (retryWithCached(pkg, addBundled, next)) return
  pkg._bundled = null
  var pkgname = pkg.name
  var ver = pkg.version
  var tarball = path.join(cachedPackageRoot({name: pkgname, version: ver}), 'package.tgz')
  var target = tempFilename('unpack')
  getCacheStat(iferr(next, function (cs) {
    log.verbose('addBundled', 'extract', tarball)
    unpack(tarball, target, null, null, cs.uid, cs.gid, iferr(next, function () {
      log.silly('addBundled', 'read tarball')
      readPackageTree(target, function (er, tree) {
        log.silly('cleanup', 'remove extracted module')
        rimraf(target, function () {
          if (tree) {
            pkg._bundled = tree.children
          }
          next(null, pkg)
        })
      })
    }))
  }))
}

// FIXME: hasGzipHeader / hasTarHeader / untarStream duplicate a lot
// of code from lib/utils/tar.js– these should be brought together.

function hasGzipHeader (c) {
  return c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08
}

function hasTarHeader (c) {
  return c[257] === 0x75 && // tar archives have 7573746172 at position
         c[258] === 0x73 && // 257 and 003030 or 202000 at position 262
         c[259] === 0x74 &&
         c[260] === 0x61 &&
         c[261] === 0x72 &&

       ((c[262] === 0x00 &&
         c[263] === 0x30 &&
         c[264] === 0x30) ||

        (c[262] === 0x20 &&
         c[263] === 0x20 &&
         c[264] === 0x00))
}

function untarStream (tarball, cb) {
  validate('SF', arguments)
  cb = once(cb)

  var tounpipe = []
  var stream
  var file = stream = fs.createReadStream(tarball)
  file.on('error', function (er) {
    er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
    er.code = 'EREADFILE'
    cb(er)
  })
  file.on('data', function OD (c) {
    if (hasGzipHeader(c)) {
      doGunzip()
    } else if (hasTarHeader(c)) {
      doUntar()
    } else {
      file.close()
      var er = new Error('Non-gzip/tarball ' + tarball)
      er.code = 'ENOTTARBALL'
      return cb(er)
    }
    file.removeListener('data', OD)
    file.emit('data', c)
    cb(null, stream)
  })

  function doGunzip () {
    var gunzip = stream.pipe(zlib.createGunzip())
    gunzip.on('error', function (er) {
      er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
      er.code = 'EGUNZIP'
      cb(er)
    })
    tounpipe.push([stream, gunzip])
    stream = gunzip
    doUntar()
  }

  function doUntar () {
    var untar = stream.pipe(tar.Parse())
    untar.on('error', function (er) {
      er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
      er.code = 'EUNTAR'
      cb(er)
    })
    tounpipe.push([stream, untar])
    stream = untar
    addClose()
  }

  function addClose () {
    stream.close = function () {
      tounpipe.forEach(function (streams) {
        streams[0].unpipe(streams[1])
      })

      file.close()
    }
  }
}
<commit_msg>fetch-package-metadata: use unpipe<commit_after>'use strict'
var fs = require('graceful-fs')
var path = require('path')
var zlib = require('zlib')

var log = require('npmlog')
var realizePackageSpecifier = require('realize-package-specifier')
var tar = require('tar')
var once = require('once')
var semver = require('semver')
var readPackageTree = require('read-package-tree')
var iferr = require('iferr')
var rimraf = require('rimraf')
var clone = require('lodash.clonedeep')
var validate = require('aproba')
var unpipe = require('unpipe')

var npm = require('./npm.js')
var mapToRegistry = require('./utils/map-to-registry.js')
var cache = require('./cache.js')
var cachedPackageRoot = require('./cache/cached-package-root.js')
var tempFilename = require('./utils/temp-filename.js')
var getCacheStat = require('./cache/get-stat.js')
var unpack = require('./utils/tar.js').unpack
var pulseTillDone = require('./utils/pulse-till-done.js')

function andLogAndFinish (spec, tracker, done) {
  validate('SF', [spec, done])
  return function (er, pkg) {
    validate('EO', arguments)
    if (er) {
      log.silly('fetchPackageMetaData', 'error for ' + spec, er)
      if (tracker) tracker.finish()
    }
    return done(er, pkg)
  }
}

module.exports = function fetchPackageMetadata (spec, where, tracker, done) {
  if (!done) {
    done = tracker || where
    tracker = null
    if (done === where) where = null
  }
  if (typeof spec === 'object') {
    var dep = spec
    spec = dep.raw
  }
  var logAndFinish = andLogAndFinish(spec, tracker, done)
  if (!dep) {
    log.silly('fetchPackageMetaData', spec)
    return realizePackageSpecifier(spec, where, iferr(logAndFinish, function (dep) {
      fetchPackageMetadata(dep, where, tracker, done)
    }))
  }
  if (dep.type === 'version' || dep.type === 'range' || dep.type === 'tag') {
    fetchNamedPackageData(dep, addRequestedAndFinish)
  } else {
    fetchOtherPackageData(spec, dep, where, addRequestedAndFinish)
  }
  function addRequestedAndFinish (er, pkg) {
    validate('EO', arguments)
    if (pkg) {
      pkg._requested = dep
      pkg._spec = spec
      pkg._where = where
      if (!pkg._args) pkg._args = []
      pkg._args.push([pkg._spec, pkg._where])
    }
    logAndFinish(er, pkg)
  }
}

function fetchOtherPackageData (spec, dep, where, next) {
  validate('SOSF', arguments)
  log.silly('fetchOtherPackageData', spec)
  cache.add(spec, null, where, false, iferr(next, function (pkg) {
    var result = clone(pkg)
    result._inCache = true
    next(null, result)
  }))
}

var regCache = {}

function fetchNamedPackageData (dep, next) {
  validate('OF', arguments)
  log.silly('fetchNamedPackageData', dep.name || dep.rawSpec)
  mapToRegistry(dep.name || dep.rawSpec, npm.config, iferr(next, function (url, auth) {
    if (regCache[url]) {
      pickVersionFromRegistryDocument(clone(regCache[url]))
    } else {
      npm.registry.get(url, {auth: auth}, pulseTillDone('fetchMetadata', iferr(next, pickVersionFromRegistryDocument)))
    }
    function returnAndAddMetadata (pkg) {
      delete pkg._from
      delete pkg._resolved
      delete pkg._shasum
      next(null, pkg)
    }
    function pickVersionFromRegistryDocument (pkg) {
      if (!regCache[url]) regCache[url] = pkg
      var versions = Object.keys(pkg.versions).sort(semver.rcompare)

      if (dep.type === 'tag') {
        var tagVersion = pkg['dist-tags'][dep.spec]
        if (pkg.versions[tagVersion]) return returnAndAddMetadata(pkg.versions[tagVersion])
      } else {
        var latestVersion = pkg['dist-tags'].latest || versions[0]

        // Find the the most recent version less than or equal
        // to latestVersion that satisfies our spec
        for (var ii = 0; ii < versions.length; ++ii) {
          if (semver.gt(versions[ii], latestVersion)) continue
          if (semver.satisfies(versions[ii], dep.spec)) {
            return returnAndAddMetadata(pkg.versions[versions[ii]])
          }
        }

        // Failing that, try finding the most recent version that matches
        // our spec
        for (var jj = 0; jj < versions.length; ++jj) {
          if (semver.satisfies(versions[jj], dep.spec)) {
            return returnAndAddMetadata(pkg.versions[versions[jj]])
          }
        }
      }

      // And failing that, we error out
      var targets = versions.length
                  ? 'Valid install targets:\n' + JSON.stringify(versions) + '\n'
                  : 'No valid targets found.'
      var er = new Error('No compatible version found: ' +
                         dep.rawSpec + '\n' + targets)
      return next(er)
    }
  }))
}

function retryWithCached (pkg, asserter, next) {
  if (!pkg._inCache) {
    cache.add(pkg._spec, null, pkg._where, false, iferr(next, function (newpkg) {
      Object.keys(newpkg).forEach(function (key) {
        if (key[0] !== '_') return
        pkg[key] = newpkg[key]
      })
      pkg._inCache = true
      return asserter(pkg, next)
    }))
  }
  return !pkg._inCache
}

module.exports.addShrinkwrap = function addShrinkwrap (pkg, next) {
  validate('OF', arguments)
  if (pkg._shrinkwrap !== undefined) return next(null, pkg)
  if (retryWithCached(pkg, addShrinkwrap, next)) return
  pkg._shrinkwrap = null
  // FIXME: cache the shrinkwrap directly
  var pkgname = pkg.name
  var ver = pkg.version
  var tarball = path.join(cachedPackageRoot({name: pkgname, version: ver}), 'package.tgz')
  untarStream(tarball, function (er, untar) {
    if (er) {
      if (er.code === 'ENOTTARBALL') {
        pkg._shrinkwrap = null
        return next()
      } else {
        return next(er)
      }
    }
    if (er) return next(er)
    var foundShrinkwrap = false
    log.silly('addShrinkwrap', 'Adding shrinkwrap to ' + pkgname)
    untar.on('entry', function (entry) {
      if (!/^(?:[^\/]+[\/])npm-shrinkwrap.json$/.test(entry.path)) return
      log.silly('addShrinkwrap', 'Found shrinkwrap at ' + entry.path)
      foundShrinkwrap = true
      var shrinkwrap = ''
      entry.on('data', function (chunk) {
        shrinkwrap += chunk
      })
      entry.on('end', function () {
        untar.close()
        log.silly('addShrinkwrap', 'Done reading shrinkwrap')
        try {
          pkg._shrinkwrap = JSON.parse(shrinkwrap)
        } catch (ex) {
          var er = new Error('Error parsing ' + pkgname + '@' + ver + "'s npm-shrinkwrap.json: " + ex.message)
          er.type = 'ESHRINKWRAP'
          return next(er)
        }
        next(null, pkg)
      })
      entry.resume()
    })
    untar.on('end', function () {
      if (!foundShrinkwrap) {
        pkg._shrinkwrap = null
        next(null, pkg)
      }
    })
  })
}

module.exports.addBundled = function addBundled (pkg, next) {
  validate('OF', arguments)
  if (pkg._bundled !== undefined) return next(null, pkg)
  if (!pkg.bundleDependencies) return next(null, pkg)
  if (retryWithCached(pkg, addBundled, next)) return
  pkg._bundled = null
  var pkgname = pkg.name
  var ver = pkg.version
  var tarball = path.join(cachedPackageRoot({name: pkgname, version: ver}), 'package.tgz')
  var target = tempFilename('unpack')
  getCacheStat(iferr(next, function (cs) {
    log.verbose('addBundled', 'extract', tarball)
    unpack(tarball, target, null, null, cs.uid, cs.gid, iferr(next, function () {
      log.silly('addBundled', 'read tarball')
      readPackageTree(target, function (er, tree) {
        log.silly('cleanup', 'remove extracted module')
        rimraf(target, function () {
          if (tree) {
            pkg._bundled = tree.children
          }
          next(null, pkg)
        })
      })
    }))
  }))
}

// FIXME: hasGzipHeader / hasTarHeader / untarStream duplicate a lot
// of code from lib/utils/tar.js– these should be brought together.

function hasGzipHeader (c) {
  return c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08
}

function hasTarHeader (c) {
  return c[257] === 0x75 && // tar archives have 7573746172 at position
         c[258] === 0x73 && // 257 and 003030 or 202000 at position 262
         c[259] === 0x74 &&
         c[260] === 0x61 &&
         c[261] === 0x72 &&

       ((c[262] === 0x00 &&
         c[263] === 0x30 &&
         c[264] === 0x30) ||

        (c[262] === 0x20 &&
         c[263] === 0x20 &&
         c[264] === 0x00))
}

function untarStream (tarball, cb) {
  validate('SF', arguments)
  cb = once(cb)

  var stream
  var file = stream = fs.createReadStream(tarball)
  var tounpipe = [file]
  file.on('error', function (er) {
    er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
    er.code = 'EREADFILE'
    cb(er)
  })
  file.on('data', function OD (c) {
    if (hasGzipHeader(c)) {
      doGunzip()
    } else if (hasTarHeader(c)) {
      doUntar()
    } else {
      file.close()
      var er = new Error('Non-gzip/tarball ' + tarball)
      er.code = 'ENOTTARBALL'
      return cb(er)
    }
    file.removeListener('data', OD)
    file.emit('data', c)
    cb(null, stream)
  })

  function doGunzip () {
    var gunzip = stream.pipe(zlib.createGunzip())
    gunzip.on('error', function (er) {
      er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
      er.code = 'EGUNZIP'
      cb(er)
    })
    tounpipe.push(gunzip)
    stream = gunzip
    doUntar()
  }

  function doUntar () {
    var untar = stream.pipe(tar.Parse())
    untar.on('error', function (er) {
      er = new Error('Error extracting ' + tarball + ' archive: ' + er.message)
      er.code = 'EUNTAR'
      cb(er)
    })
    tounpipe.push(untar)
    stream = untar
    addClose()
  }

  function addClose () {
    stream.close = function () {
      tounpipe.forEach(function (stream) {
        unpipe(stream)
      })

      if (file.close) file.close()
      if (file.destroy) file.destroy()
    }
  }
}
<|endoftext|>


<commit_before>if (typeof HotPotatoe === "undefined") {
    HotPotatoe = {};
}

/**
 * Player
 *
 * @param {HotPotatoe.Game} game
 * @param {string} id - A unique player ID
 * @param {boolean} [isCurrentPlayer=false] - Flag to indicate if this player is controlled by current user
 * @constructor
 */
HotPotatoe.Player = function (game, id, isCurrentPlayer) {
    this.parent = game;
    this.phaser = game.phaser;
    this.id = id;
    this.isCurrentPlayer = false;
    this.force = 15;
    this.maxVelocity = 200;
    this.isHotPotatoe = false;
    this.canMove = true;

    if (typeof isCurrentPlayer !== 'undefined') {
        this.isCurrentPlayer = isCurrentPlayer;
    }
};

/**
 * Pre-load player assets
 */
HotPotatoe.Player.prototype.preload = function() {
    this.assetId = this.parent.assetIds.players;
    if (this.isCurrentPlayer) {
        this.assetId = this.parent.assetIds.currentPlayer;
    }
};

/**
 * Create player
 */
HotPotatoe.Player.prototype.create = function() {
    var x = Math.floor((Math.random() * 700) + 1);
    var y = Math.floor((Math.random() * 500) + 1);
    this.sprite = this.phaser.add.sprite(x, y, this.assetId);
    if (Meteor.isClient) {
        //On client we hide players until their positions get synced
        this.sprite.visible = false;

        this.halo = this.phaser.add.graphics(x, y);
        this.halo.lineStyle(1, 0xffffff);
        this.halo.drawCircle(0, 0, 14);
        this.halo.visible = false;
        // with phaser 2.2, repeat value = -1 for unlimited repeat
        this.phaser.add.tween(this.halo.scale).to( { x: 1.7, y: 1.7 }, 600, Phaser.Easing.Linear.None, true, 0, 100, false);
    }
    this.sprite.playerId = this.id;

    if (Meteor.isServer) {
        // We need to enable physics on the player
        this.phaser.physics.p2.enable(this.sprite);
        this.sprite.body.setCircle(15);

        // Adding a collision event for player that is hot potato
        if(this.isHotPotatoe) {
            this.jumpingHotPotatoSignalBinding = this.sprite.body.onBeginContact.add(this.jumpingHotPotatoCallback, this);
        }
    } else {
        //We need to center anchor on client because
        //when we set a p2 physics body on this sprite on server
        //the anchor is centered implicitly
        this.sprite.anchor.setTo(0.5, 0.5);

        // Display player name
        var currentRoom =  GameRooms.currentRoom();
        var _player =_.findWhere(currentRoom.players, {id: this.id});
        this.playerNameText = this.phaser.add.text(x, y + 23 , _player.name.substring(0, 15), {
            font: "14px Arial",
            fill: "#ffffff",
            align: "center"
        });
        this.playerNameText.anchor.setTo(0.5, 0.5);
        this.playerNameText.visible = false;//will be displayed when player positions are synced
    }

    // If this player is controlled by the user
    // Camera should follow him
    if (this.isCurrentPlayer) {
        this.phaser.camera.follow(this.sprite);
    }
};

/**
 * Update player
 */
HotPotatoe.Player.prototype.update = function() {
    //Handle player input and update sprite sync
    if (Meteor.isServer && this.canMove) {
        if (UserActions[this.id].cursors.left.isDown) {
            this.sprite.body.data.force[0] += this.force;
        } else if (UserActions[this.id].cursors.right.isDown) {
            this.sprite.body.data.force[0] -= this.force;
        }
        if (UserActions[this.id].cursors.up.isDown) {
            this.sprite.body.data.force[1] += this.force;
        } else if (UserActions[this.id].cursors.down.isDown) {
            this.sprite.body.data.force[1] -= this.force;
        }
        // Apply max velocity
        if (this.sprite.body.velocity.x < -this.maxVelocity) {
            this.sprite.body.velocity.x = -this.maxVelocity;
        }
        if (this.sprite.body.velocity.x > this.maxVelocity) {
            this.sprite.body.velocity.x = this.maxVelocity;
        }
        if (this.sprite.body.velocity.y < -this.maxVelocity) {
            this.sprite.body.velocity.y = -this.maxVelocity;
        }
        if (this.sprite.body.velocity.y > this.maxVelocity) {
            this.sprite.body.velocity.y = this.maxVelocity;
        }
    }

    if (Meteor.isClient) {
        this.playerNameText.x = this.sprite.x;
        this.playerNameText.y = this.sprite.y + 23;
        this.playerNameText.visible = false;
        if (this.sprite.visible) {
            this.playerNameText.visible = true;
        }
        this.halo.visible = this.isHotPotatoe && this.sprite.visible;
        this.halo.x = this.sprite.x - 0.7;
        this.halo.y = this.sprite.y - 0.4;
    }
};

/**
 * Defines the hot potatoe flag attribute state,
 * and change sprite texture
 * @param {boolean} hotpotatoe
 */
HotPotatoe.Player.prototype.setHotPotatoe = function(hotpotatoe) {
    this.isHotPotatoe = hotpotatoe;
    if (this.sprite) {
        var newassetId = this.parent.assetIds.players;
        if (hotpotatoe) {
            newassetId = this.parent.assetIds.hotpotatoe;
        } else if (this.isCurrentPlayer) {
            newassetId = this.parent.assetIds.currentPlayer;
        }

        // change sprite texture
        if (this.assetId != newassetId) {
            this.assetId = newassetId;
            this.sprite.loadTexture(newassetId, 0);
        }

        // When a player is defined hot potato, a collision event is added after a delay
        // to make possible jumping the hot potato from player to player
        if (hotpotatoe && Meteor.isServer) {
            this.phaser.time.events.repeat(600, 1, function() {
                this.jumpingHotPotatoSignalBinding = this.sprite.body.onBeginContact.add(this.jumpingHotPotatoCallback, this);
            }, this);
        }
    }

};

/**
 * Callback which is called when a player collides with an object
 *
 * @param {Phaser.Physics.P2.Body} objectCollided
 */
HotPotatoe.Player.prototype.jumpingHotPotatoCallback = function(objectCollided) {
    if (objectCollided && objectCollided.sprite && objectCollided.sprite.playerId) {
        var _playerCollided = _.findWhere(this.parent.players, {id: objectCollided.sprite.playerId});
        _playerCollided.setHotPotatoe(true);
        this.setHotPotatoe(false);
        this.jumpingHotPotatoSignalBinding.detach();
    }
};<commit_msg>Minors updates to match with phaser 2.2.2<commit_after>if (typeof HotPotatoe === "undefined") {
    HotPotatoe = {};
}

/**
 * Player
 *
 * @param {HotPotatoe.Game} game
 * @param {string} id - A unique player ID
 * @param {boolean} [isCurrentPlayer=false] - Flag to indicate if this player is controlled by current user
 * @constructor
 */
HotPotatoe.Player = function (game, id, isCurrentPlayer) {
    this.parent = game;
    this.phaser = game.phaser;
    this.id = id;
    this.isCurrentPlayer = false;
    this.force = 15;
    this.maxVelocity = 200;
    this.isHotPotatoe = false;
    this.canMove = true;

    if (typeof isCurrentPlayer !== 'undefined') {
        this.isCurrentPlayer = isCurrentPlayer;
    }
};

/**
 * Pre-load player assets
 */
HotPotatoe.Player.prototype.preload = function() {
    this.assetId = this.parent.assetIds.players;
    if (this.isCurrentPlayer) {
        this.assetId = this.parent.assetIds.currentPlayer;
    }
};

/**
 * Create player
 */
HotPotatoe.Player.prototype.create = function() {
    var x = Math.floor((Math.random() * 700) + 1);
    var y = Math.floor((Math.random() * 500) + 1);
    this.sprite = this.phaser.add.sprite(x, y, this.assetId);
    if (Meteor.isClient) {
        //On client we hide players until their positions get synced
        this.sprite.visible = false;

        this.halo = this.phaser.add.graphics(x, y);
        this.halo.lineStyle(1, 0xffffff);
        this.halo.drawCircle(0, 0, this.sprite.width);
        this.halo.visible = false;
        this.phaser.add.tween(this.halo.scale).to({x: 1.7, y: 1.7}, 600, Phaser.Easing.Linear.None, true, 0, -1, false);
    }
    this.sprite.playerId = this.id;

    if (Meteor.isServer) {
        // We need to enable physics on the player
        this.phaser.physics.p2.enable(this.sprite);
        this.sprite.body.setCircle(15);

        // Adding a collision event for player that is hot potato
        if(this.isHotPotatoe) {
            this.jumpingHotPotatoSignalBinding = this.sprite.body.onBeginContact.add(this.jumpingHotPotatoCallback, this);
        }
    } else {
        //We need to center anchor on client because
        //when we set a p2 physics body on this sprite on server
        //the anchor is centered implicitly
        this.sprite.anchor.setTo(0.5, 0.5);

        // Display player name
        var currentRoom =  GameRooms.currentRoom();
        var _player =_.findWhere(currentRoom.players, {id: this.id});
        this.playerNameText = this.phaser.add.text(x, y + 25 , _player.name.substring(0, 15), {
            font: "14px Arial",
            fill: "#ffffff",
            align: "center"
        });
        this.playerNameText.anchor.setTo(0.5, 0.5);
        this.playerNameText.visible = false;//will be displayed when player positions are synced
    }

    // If this player is controlled by the user
    // Camera should follow him
    if (this.isCurrentPlayer) {
        this.phaser.camera.follow(this.sprite);
    }
};

/**
 * Update player
 */
HotPotatoe.Player.prototype.update = function() {
    //Handle player input and update sprite sync
    if (Meteor.isServer && this.canMove) {
        if (UserActions[this.id].cursors.left.isDown) {
            this.sprite.body.data.force[0] += this.force;
        } else if (UserActions[this.id].cursors.right.isDown) {
            this.sprite.body.data.force[0] -= this.force;
        }
        if (UserActions[this.id].cursors.up.isDown) {
            this.sprite.body.data.force[1] += this.force;
        } else if (UserActions[this.id].cursors.down.isDown) {
            this.sprite.body.data.force[1] -= this.force;
        }
        // Apply max velocity
        if (this.sprite.body.velocity.x < -this.maxVelocity) {
            this.sprite.body.velocity.x = -this.maxVelocity;
        }
        if (this.sprite.body.velocity.x > this.maxVelocity) {
            this.sprite.body.velocity.x = this.maxVelocity;
        }
        if (this.sprite.body.velocity.y < -this.maxVelocity) {
            this.sprite.body.velocity.y = -this.maxVelocity;
        }
        if (this.sprite.body.velocity.y > this.maxVelocity) {
            this.sprite.body.velocity.y = this.maxVelocity;
        }
    }

    if (Meteor.isClient) {
        this.playerNameText.x = this.sprite.x;
        this.playerNameText.y = this.sprite.y + 25;
        this.playerNameText.visible = false;
        if (this.sprite.visible) {
            this.playerNameText.visible = true;
        }
        this.halo.visible = this.isHotPotatoe && this.sprite.visible;
        this.halo.x = this.sprite.x - 0.7;
        this.halo.y = this.sprite.y - 0.4;
    }
};

/**
 * Defines the hot potatoe flag attribute state,
 * and change sprite texture
 * @param {boolean} hotpotatoe
 */
HotPotatoe.Player.prototype.setHotPotatoe = function(hotpotatoe) {
    this.isHotPotatoe = hotpotatoe;
    if (this.sprite) {
        var newassetId = this.parent.assetIds.players;
        if (hotpotatoe) {
            newassetId = this.parent.assetIds.hotpotatoe;
        } else if (this.isCurrentPlayer) {
            newassetId = this.parent.assetIds.currentPlayer;
        }

        // change sprite texture
        if (this.assetId != newassetId) {
            this.assetId = newassetId;
            this.sprite.loadTexture(newassetId, 0);
        }

        // When a player is defined hot potato, a collision event is added after a delay
        // to make possible jumping the hot potato from player to player
        if (hotpotatoe && Meteor.isServer) {
            this.phaser.time.events.repeat(600, 1, function() {
                this.jumpingHotPotatoSignalBinding = this.sprite.body.onBeginContact.add(this.jumpingHotPotatoCallback, this);
            }, this);
        }
    }

};

/**
 * Callback which is called when a player collides with an object
 *
 * @param {Phaser.Physics.P2.Body} objectCollided
 */
HotPotatoe.Player.prototype.jumpingHotPotatoCallback = function(objectCollided) {
    if (objectCollided && objectCollided.sprite && objectCollided.sprite.playerId) {
        var _playerCollided = _.findWhere(this.parent.players, {id: objectCollided.sprite.playerId});
        _playerCollided.setHotPotatoe(true);
        this.setHotPotatoe(false);
        this.jumpingHotPotatoSignalBinding.detach();
    }
};<|endoftext|>


<commit_before>'use strict'

const dedent = require('dedent')
const yargs = require('yargs')
const {app} = require('electron')
const path = require('path')
const fs = require('fs-plus')

module.exports = function parseCommandLine (processArgs) {
  const options = yargs(processArgs).wrap(yargs.terminalWidth())
  const version = app.getVersion()
  options.usage(
    dedent`Atom Editor v${version}

    Usage: atom [options] [path ...]

    One or more paths to files or folders may be specified. If there is an
    existing Atom window that contains all of the given folders, the paths
    will be opened in that window. Otherwise, they will be opened in a new
    window.

    Environment Variables:

      ATOM_DEV_RESOURCE_PATH  The path from which Atom loads source code in dev mode.
                              Defaults to \`~/github/atom\`.

      ATOM_HOME               The root path for all configuration files and folders.
                              Defaults to \`~/.atom\`.`
  )
  // Deprecated 1.0 API preview flag
  options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.')
  options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.')
  options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
  options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.')
  options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
  options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
  options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
  options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.')
  options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.')
  options.boolean('safe').describe(
    'safe',
    'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.'
  )
  options.boolean('benchmark').describe('benchmark', 'Open a new window that runs the specified benchmarks.')
  options.boolean('benchmark-test').describe('benchmark--test', 'Run a faster version of the benchmarks in headless mode.')
  options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
  options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.')
  options.string('timeout').describe(
    'timeout',
    'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).'
  )
  options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.')
  options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
  options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.')
  options.string('socket-path')
  options.string('user-data-dir')
  options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.')

  const args = options.argv

  if (args.help) {
    process.stdout.write(options.help())
    process.exit(0)
  }

  if (args.version) {
    process.stdout.write(
      `Atom    : ${app.getVersion()}\n` +
      `Electron: ${process.versions.electron}\n` +
      `Chrome  : ${process.versions.chrome}\n` +
      `Node    : ${process.versions.node}\n`
    )
    process.exit(0)
  }

  const addToLastWindow = args['add']
  const safeMode = args['safe']
  const pathsToOpen = args._
  const benchmark = args['benchmark']
  const benchmarkTest = args['benchmark-test']
  const test = args['test']
  const mainProcess = args['main-process']
  const timeout = args['timeout']
  const newWindow = args['new-window']
  let executedFrom = null
  if (args['executed-from'] && args['executed-from'].toString()) {
    executedFrom = args['executed-from'].toString()
  } else {
    executedFrom = process.cwd()
  }

  let pidToKillWhenClosed = null
  if (args['wait']) {
    pidToKillWhenClosed = args['pid']
  }

  const logFile = args['log-file']
  const socketPath = args['socket-path']
  const userDataDir = args['user-data-dir']
  const profileStartup = args['profile-startup']
  const clearWindowState = args['clear-window-state']
  const urlsToOpen = []
  let devMode = args['dev']
  let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
  let resourcePath = null

  if (args['resource-path']) {
    devMode = true
    devResourcePath = args['resource-path']
  }

  if (test) {
    devMode = true
  }

  if (devMode) {
    resourcePath = devResourcePath
  }

  if (!fs.statSyncNoException(resourcePath)) {
    resourcePath = path.dirname(path.dirname(__dirname))
  }

  if (args['path-environment']) {
    // On Yosemite the $PATH is not inherited by the "open" command, so we have to
    // explicitly pass it by command line, see http://git.io/YC8_Ew.
    process.env.PATH = args['path-environment']
  }

  resourcePath = normalizeDriveLetterName(resourcePath)
  devResourcePath = normalizeDriveLetterName(devResourcePath)

  return {
    resourcePath,
    devResourcePath,
    pathsToOpen,
    urlsToOpen,
    executedFrom,
    test,
    version,
    pidToKillWhenClosed,
    devMode,
    safeMode,
    newWindow,
    logFile,
    socketPath,
    userDataDir,
    profileStartup,
    timeout,
    clearWindowState,
    addToLastWindow,
    mainProcess,
    benchmark,
    benchmarkTest,
    env: process.env
  }
}

function normalizeDriveLetterName (filePath) {
  if (process.platform === 'win32') {
    return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':')
  } else {
    return filePath
  }
}
<commit_msg>Document enable-electron-logging option<commit_after>'use strict'

const dedent = require('dedent')
const yargs = require('yargs')
const {app} = require('electron')
const path = require('path')
const fs = require('fs-plus')

module.exports = function parseCommandLine (processArgs) {
  const options = yargs(processArgs).wrap(yargs.terminalWidth())
  const version = app.getVersion()
  options.usage(
    dedent`Atom Editor v${version}

    Usage: atom [options] [path ...]

    One or more paths to files or folders may be specified. If there is an
    existing Atom window that contains all of the given folders, the paths
    will be opened in that window. Otherwise, they will be opened in a new
    window.

    Environment Variables:

      ATOM_DEV_RESOURCE_PATH  The path from which Atom loads source code in dev mode.
                              Defaults to \`~/github/atom\`.

      ATOM_HOME               The root path for all configuration files and folders.
                              Defaults to \`~/.atom\`.`
  )
  // Deprecated 1.0 API preview flag
  options.alias('1', 'one').boolean('1').describe('1', 'This option is no longer supported.')
  options.boolean('include-deprecated-apis').describe('include-deprecated-apis', 'This option is not currently supported.')
  options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
  options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the main process in the foreground.')
  options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
  options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
  options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
  options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.')
  options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.')
  options.boolean('safe').describe(
    'safe',
    'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.'
  )
  options.boolean('benchmark').describe('benchmark', 'Open a new window that runs the specified benchmarks.')
  options.boolean('benchmark-test').describe('benchmark--test', 'Run a faster version of the benchmarks in headless mode.')
  options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
  options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.')
  options.string('timeout').describe(
    'timeout',
    'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).'
  )
  options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.')
  options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
  options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.')
  options.string('socket-path')
  options.string('user-data-dir')
  options.boolean('clear-window-state').describe('clear-window-state', 'Delete all Atom environment state.')
  options.boolean('enable-electron-logging').describe('enable-electron-logging', 'Enable low-level logging messages from Electron.')

  const args = options.argv

  if (args.help) {
    process.stdout.write(options.help())
    process.exit(0)
  }

  if (args.version) {
    process.stdout.write(
      `Atom    : ${app.getVersion()}\n` +
      `Electron: ${process.versions.electron}\n` +
      `Chrome  : ${process.versions.chrome}\n` +
      `Node    : ${process.versions.node}\n`
    )
    process.exit(0)
  }

  const addToLastWindow = args['add']
  const safeMode = args['safe']
  const pathsToOpen = args._
  const benchmark = args['benchmark']
  const benchmarkTest = args['benchmark-test']
  const test = args['test']
  const mainProcess = args['main-process']
  const timeout = args['timeout']
  const newWindow = args['new-window']
  let executedFrom = null
  if (args['executed-from'] && args['executed-from'].toString()) {
    executedFrom = args['executed-from'].toString()
  } else {
    executedFrom = process.cwd()
  }

  let pidToKillWhenClosed = null
  if (args['wait']) {
    pidToKillWhenClosed = args['pid']
  }

  const logFile = args['log-file']
  const socketPath = args['socket-path']
  const userDataDir = args['user-data-dir']
  const profileStartup = args['profile-startup']
  const clearWindowState = args['clear-window-state']
  const urlsToOpen = []
  let devMode = args['dev']
  let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
  let resourcePath = null

  if (args['resource-path']) {
    devMode = true
    devResourcePath = args['resource-path']
  }

  if (test) {
    devMode = true
  }

  if (devMode) {
    resourcePath = devResourcePath
  }

  if (!fs.statSyncNoException(resourcePath)) {
    resourcePath = path.dirname(path.dirname(__dirname))
  }

  if (args['path-environment']) {
    // On Yosemite the $PATH is not inherited by the "open" command, so we have to
    // explicitly pass it by command line, see http://git.io/YC8_Ew.
    process.env.PATH = args['path-environment']
  }

  resourcePath = normalizeDriveLetterName(resourcePath)
  devResourcePath = normalizeDriveLetterName(devResourcePath)

  return {
    resourcePath,
    devResourcePath,
    pathsToOpen,
    urlsToOpen,
    executedFrom,
    test,
    version,
    pidToKillWhenClosed,
    devMode,
    safeMode,
    newWindow,
    logFile,
    socketPath,
    userDataDir,
    profileStartup,
    timeout,
    clearWindowState,
    addToLastWindow,
    mainProcess,
    benchmark,
    benchmarkTest,
    env: process.env
  }
}

function normalizeDriveLetterName (filePath) {
  if (process.platform === 'win32') {
    return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':')
  } else {
    return filePath
  }
}
<|endoftext|>


<commit_before>'use strict';

/* Given a storage node
return a list of every set of cost storage links at each timestep.
*/

var cost = require('./cost');
var bound = require('./bound');
var netu = require('./split_utils');
var evaporation = require('./evaporation');
var u=require('./utils');

module.exports = function(stor, steps) {
  var p = stor.properties;
  var id= p.hobbes.networkId;
  var step_costs;
  var step_bounds;
  var i,k;
  var rows = [];

  // Assume there IS a storage, otherwise, we need steps!
  var cap = p.storage;

  // Boundary conditions
  var initial=p.initialstorage;
  var ending=p.endingstorage;
  var first=null;
  var last=null;

  var step_keys={};
  steps.forEach((s) => {
    step_keys[s] =1;
  });

  // Get initial and Final storage capacities
  for( i = 1; i < cap.length; i++ ) { // i=0 is header;
    if (step_keys[cap[i][0]]) {
      if (! first) {
        if ( i > 1 ) initial=cap[i-1][1];
        first++;
      }
      last=i;
    }
  }
  if (last !== cap.length-1 && last !== null) {
    ending=cap[last][1];
  }

  // Add Initial [i,j,k,cost,amplitude,lower,upper]
  rows.push(['INITIAL',u.id(id,steps[0]),0,0,1,initial,initial]);

  var step_bounds = bound(p.bounds, steps);
  var step_costs = cost(p.costs, step_bounds, steps, p.prmname);

  var step_amp = evaporation(stor, steps);
  var i;
  var stepBounds, costs;
  var clb,cub;
  var amp;
  var next;

  for(i = 0; i < steps.length; i++ ) { // i=0 is header;
    stepBounds = step_bounds[i];
    costs = step_costs[i];
    amp = step_amp[i];

    if(i === steps.length-1 ) { // Fixed to final storage
      // JM fix for issue 35
      if( ending === null ) {
        stepBounds.LB = 0;
      } else {
        stepBounds.LB = ending;
      }
      stepBounds.UB = ending;

      next = 'FINAL';
      rows.push([
        u.id(id,steps[i]),
        next,
        0,
        0,
        1,
        stepBounds.LB,
        stepBounds.UB
      ]);

    } else {
      next = u.id(id,steps[i+1]);

      for( k = 0; k < costs.length; k++ ) {
        if( costs[k].lb > stepBounds.LB ) {
          clb = costs[k].lb;
        } else if ( (costs[k].ub || 0) <= stepBounds.LB ) {
          clb = costs[k].ub || 0;
        } else {
          clb = stepBounds.LB;
        }

        stepBounds.LB -= clb;
        if( stepBounds.UB === null ) {
          cub = costs[k].ub;
        } else {
          if( costs[k].ub !== null && costs[k].ub <= stepBounds.LB ) {
            cub = costs[k].ub
          } else {
            cub = stepBounds.LB;
          }

          stepBounds.UB -= cub;
        }

        if( cub === null || cub > 0) {
          rows.push([
            u.id(id,steps[i]),
            next,
            k,
            costs[k].cost,
            amp,
            clb,
            cub
          ]);
        }
      }
    }
  }

return rows;
};
<commit_msg>adding attempted fix for latest part of issue #36<commit_after>'use strict';

/* Given a storage node
return a list of every set of cost storage links at each timestep.
*/

var cost = require('./cost');
var bound = require('./bound');
var netu = require('./split_utils');
var evaporation = require('./evaporation');
var u=require('./utils');

module.exports = function(stor, steps) {
  var p = stor.properties;
  var id= p.hobbes.networkId;
  var step_costs;
  var step_bounds;
  var i,k;
  var rows = [];

  // Assume there IS a storage, otherwise, we need steps!
  var cap = p.storage;

  // Boundary conditions
  var initial=p.initialstorage;
  var ending=p.endingstorage;
  var first=null;
  var last=null;

  var step_keys={};
  steps.forEach((s) => {
    step_keys[s] =1;
  });

  // Get initial and Final storage capacities
  for( i = 1; i < cap.length; i++ ) { // i=0 is header;
    if (step_keys[cap[i][0]]) {
      if (! first) {
        if ( i > 1 ) initial=cap[i-1][1];
        first++;
      }
      last=i;
    }
  }
  if (last !== cap.length-1 && last !== null) {
    ending=cap[last][1];
  }

  // Add Initial [i,j,k,cost,amplitude,lower,upper]
  rows.push(['INITIAL',u.id(id,steps[0]),0,0,1,initial,initial]);

  var step_bounds = bound(p.bounds, steps);
  var step_costs = cost(p.costs, step_bounds, steps, p.prmname);

  var step_amp = evaporation(stor, steps);
  var i;
  var stepBounds, costs;
  var clb,cub;
  var amp;
  var next;

  for(i = 0; i < steps.length; i++ ) { // i=0 is header;
    stepBounds = step_bounds[i];
    costs = step_costs[i];
    amp = step_amp[i];

    if(i === steps.length-1 ) { // Fixed to final storage
      // JM fix for issue 35
      if( ending === null ) {
        stepBounds.LB = 0;
      } else {
        stepBounds.LB = ending;
      }
      stepBounds.UB = ending;

      next = 'FINAL';
      rows.push([
        u.id(id,steps[i]),
        next,
        0,
        0,
        1,
        stepBounds.LB,
        stepBounds.UB
      ]);

    } else {
      next = u.id(id,steps[i+1]);

      for( k = 0; k < costs.length; k++ ) {
        if( costs[k].lb > stepBounds.LB ) {
          clb = costs[k].lb;
        } else if ( (costs[k].ub || 0) <= stepBounds.LB ) {
          clb = costs[k].ub || 0;
        } else {
          clb = stepBounds.LB;
        }

        stepBounds.LB -= clb;
        if( stepBounds.UB === null ) {
          cub = costs[k].ub;
        } else {
          if( costs[k].ub !== null && costs[k].ub <= stepBounds.LB ) {
            cub = costs[k].ub
          /** start of final fix for issue #36 */
          } else if( k === costs.length - 1 ) {
            cub = stepBounds.UB - clb;
          /** end of final fix for issue #36 */
          } else {
            cub = stepBounds.LB;
          }

          stepBounds.UB -= cub;
        }

        if( cub === null || cub > 0) {
          rows.push([
            u.id(id,steps[i]),
            next,
            k,
            costs[k].cost,
            amp,
            clb,
            cub
          ]);
        }
      }
    }
  }

return rows;
};
<|endoftext|>