<commit_before>var BaseTexture = require('./BaseTexture'),
    VideoBaseTexture = require('./VideoBaseTexture'),
    TextureUvs = require('./TextureUvs'),
    eventTarget = require('../utils/eventTarget'),
    math = require('../math'),
    utils = require('../utils');

/**
 * A texture stores the information that represents an image or part of an image. It cannot be added
 * to the display list directly. Instead use it as the texture for a Sprite. If no frame is provided then the whole image is used.
 *
 * @class
 * @mixes eventTarget
 * @namespace PIXI
 * @param baseTexture {BaseTexture} The base texture source to create the texture from
 * @param [frame] {Rectangle} The rectangle frame of the texture to show
 * @param [crop] {Rectangle} The area of original texture
 * @param [trim] {Rectangle} Trimmed texture rectangle
 * @param [rotate] {Rectangle} indicates if the texture should be rotated 90 degrees ( used by texture packer )
 */
function Texture(baseTexture, frame, crop, trim, rotate)
{
    console.log(trim, frame, crop, "......")
    /**
     * Does this Texture have any frame data assigned to it?
     *
     * @member {boolean}
     */
    this.noFrame = false;

    if (!frame)
    {
        this.noFrame = true;
        frame = new math.Rectangle(0, 0, 1, 1);
    }

    if (baseTexture instanceof Texture)
    {
        baseTexture = baseTexture.baseTexture;
    }

  //  console.log(frame);

    /**
     * The base texture that this texture uses.
     *
     * @member {BaseTexture}
     */
    this.baseTexture = baseTexture;

    /**
     * The frame specifies the region of the base texture that this texture uses
     *
     * @member {Rectangle}
     * @private
     */
    this._frame = frame;

    /**
     * The texture trim data.
     *
     * @member {Rectangle}
     */
    this.trim = trim;

    /**
     * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
     *
     * @member {boolean}
     */
    this.valid = false;

    /**
     * This will let a renderer know that a texture has been updated (used mainly for webGL uv updates)
     *
     * @member {boolean}
     */
    this.requiresUpdate = false;

    /**
     * The WebGL UV data cache.
     *
     * @member {object}
     * @private
     */
    this._uvs = null;

    /**
     * The width of the Texture in pixels.
     *
     * @member {number}
     */
    this.width = 0;

    /**
     * The height of the Texture in pixels.
     *
     * @member {number}
     */
    this.height = 0;

    /**
     * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
     * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
     *
     * @member {Rectangle}
     */
    this.crop = crop || frame;//new math.Rectangle(0, 0, 1, 1);

    /**
     * The rotation value of the texture.
     *
     * @private
     * @member {number}
     */
    this.rotate = !!rotate;

    if (baseTexture.hasLoaded)
    {
        if (this.noFrame)
        {
            frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
        }
        this.frame = frame;
    }
    else
    {
        baseTexture.addEventListener('loaded', this.onBaseTextureLoaded.bind(this));
    }
}

Texture.prototype.constructor = Texture;
module.exports = Texture;

eventTarget.mixin(Texture.prototype);

Object.defineProperties(Texture.prototype, {
    frame: {
        get: function ()
        {
            return this._frame;
        },
        set: function (frame)
        {
            this._frame = frame;

            this.noFrame = false;

            this.width = frame.width;
            this.height = frame.height;

            this.crop = frame;

            if (!this.trim && !this.rotate && (frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height))
            {
                throw new Error('Texture Error: frame does not fit inside the base Texture dimensions ' + this);
            }

            this.valid = frame && frame.width && frame.height && this.baseTexture.source && this.baseTexture.hasLoaded;

            if (this.trim)
            {

                this.width = this.trim.width;
                this.height = this.trim.height;
                this._frame.width = this.trim.width;
                this._frame.height = this.trim.height;
            }

            if (this.valid)
            {
                this._updateUvs();
            }
        }
    }
});

/**
 * Updates this texture on the gpu.
 *
 */
Texture.prototype.update = function ()
{
    this.baseTexture.update();
};

/**
 * Called when the base texture is loaded
 *
 * @private
 */
Texture.prototype.onBaseTextureLoaded = function ()
{
    var baseTexture = this.baseTexture;
    baseTexture.removeEventListener('loaded', this.onLoaded);

    // TODO this code looks confusing.. boo to abusing getters and setterss!
    if (this.noFrame)
    {
        this.frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
    }
    else
    {
        this.frame = this._frame;
    }

    this.dispatchEvent( { type: 'update', content: this } );
};

/**
 * Destroys this texture
 *
 * @param destroyBase {boolean} Whether to destroy the base texture as well
 */
Texture.prototype.destroy = function (destroyBase)
{
    if (destroyBase)
    {
        this.baseTexture.destroy();
    }

    this.valid = false;
};

/**
 * Updates the internal WebGL UV cache.
 *
 * @private
 */
Texture.prototype._updateUvs = function ()
{
    if (!this._uvs)
    {
        this._uvs = new TextureUvs();
    }

    this._uvs.set(this.crop, this.baseTexture, this.rotate);
};

/**
 * Helper function that creates a Texture object from the given image url.
 * If the image is not in the texture cache it will be  created and loaded.
 *
 * @static
 * @param imageUrl {string} The image url of the texture
 * @param crossorigin {boolean} Whether requests should be treated as crossorigin
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return Texture
 */
Texture.fromImage = function (imageUrl, crossorigin, scaleMode)
{
    var texture = utils.TextureCache[imageUrl];

    if (!texture)
    {
        texture = new Texture(BaseTexture.fromImage(imageUrl, crossorigin, scaleMode));
        utils.TextureCache[imageUrl] = texture;
    }

    return texture;
};

Texture.fromFrame = function (frameId)
{
    var texture = utils.TextureCache[frameId];

    if (!texture)
    {
        throw new Error('The frameId "' + frameId + '" does not exist in the texture cache' + this);
    }

    return texture;
};

/**
 * Helper function that creates a new Texture based on the given canvas element.
 *
 * @static
 * @param canvas {Canvas} The canvas element source of the texture
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return {Texture}
 */
Texture.fromCanvas = function (canvas, scaleMode)
{
    return new Texture(BaseTexture.fromCanvas(canvas, scaleMode));
};

/**
 * Helper function that creates a new Texture based on the given video element.
 *
 * @static
 * @param video {HTMLVideoElement}
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return {Texture} A Texture
 */
Texture.fromVideo = function (video, scaleMode)
{
    return new Texture(VideoBaseTexture.baseTextureFromVideo(video, scaleMode));
};

/**
 * Adds a texture to the global utils.TextureCache. This cache is shared across the whole PIXI object.
 *
 * @static
 * @param texture {Texture} The Texture to add to the cache.
 * @param id {string} The id that the texture will be stored against.
 */
Texture.addTextureToCache = function (texture, id)
{
    utils.TextureCache[id] = texture;
};

/**
 * Remove a texture from the global utils.TextureCache.
 *
 * @static
 * @param id {string} The id of the texture to be removed
 * @return {Texture} The texture that was removed
 */
Texture.removeTextureFromCache = function (id)
{
    var texture = utils.TextureCache[id];

    delete utils.TextureCache[id];
    delete utils.BaseTextureCache[id];

    return texture;
};

Texture.emptyTexture = new Texture(new BaseTexture());
<commit_msg>Fixed trimmed texture issue<commit_after>var BaseTexture = require('./BaseTexture'),
    VideoBaseTexture = require('./VideoBaseTexture'),
    TextureUvs = require('./TextureUvs'),
    eventTarget = require('../utils/eventTarget'),
    math = require('../math'),
    utils = require('../utils');

/**
 * A texture stores the information that represents an image or part of an image. It cannot be added
 * to the display list directly. Instead use it as the texture for a Sprite. If no frame is provided then the whole image is used.
 *
 * @class
 * @mixes eventTarget
 * @namespace PIXI
 * @param baseTexture {BaseTexture} The base texture source to create the texture from
 * @param [frame] {Rectangle} The rectangle frame of the texture to show
 * @param [crop] {Rectangle} The area of original texture
 * @param [trim] {Rectangle} Trimmed texture rectangle
 * @param [rotate] {Rectangle} indicates if the texture should be rotated 90 degrees ( used by texture packer )
 */
function Texture(baseTexture, frame, crop, trim, rotate)
{
    console.log(trim, frame, crop, "......")
    /**
     * Does this Texture have any frame data assigned to it?
     *
     * @member {boolean}
     */
    this.noFrame = false;

    if (!frame)
    {
        this.noFrame = true;
        frame = new math.Rectangle(0, 0, 1, 1);
    }

    if (baseTexture instanceof Texture)
    {
        baseTexture = baseTexture.baseTexture;
    }

  //  console.log(frame);

    /**
     * The base texture that this texture uses.
     *
     * @member {BaseTexture}
     */
    this.baseTexture = baseTexture;

    /**
     * The frame specifies the region of the base texture that this texture uses
     *
     * @member {Rectangle}
     * @private
     */
    this._frame = frame;

    /**
     * The texture trim data.
     *
     * @member {Rectangle}
     */
    this.trim = trim;

    /**
     * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
     *
     * @member {boolean}
     */
    this.valid = false;

    /**
     * This will let a renderer know that a texture has been updated (used mainly for webGL uv updates)
     *
     * @member {boolean}
     */
    this.requiresUpdate = false;

    /**
     * The WebGL UV data cache.
     *
     * @member {object}
     * @private
     */
    this._uvs = null;

    /**
     * The width of the Texture in pixels.
     *
     * @member {number}
     */
    this.width = 0;

    /**
     * The height of the Texture in pixels.
     *
     * @member {number}
     */
    this.height = 0;

    /**
     * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
     * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
     *
     * @member {Rectangle}
     */
    this.crop = crop || frame;//new math.Rectangle(0, 0, 1, 1);

    /**
     * The rotation value of the texture.
     *
     * @private
     * @member {number}
     */
    this.rotate = !!rotate;

    if (baseTexture.hasLoaded)
    {
        if (this.noFrame)
        {
            frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
        }
        this.frame = frame;
    }
    else
    {
        baseTexture.addEventListener('loaded', this.onBaseTextureLoaded.bind(this));
    }
}

Texture.prototype.constructor = Texture;
module.exports = Texture;

eventTarget.mixin(Texture.prototype);

Object.defineProperties(Texture.prototype, {
    frame: {
        get: function ()
        {
            return this._frame;
        },
        set: function (frame)
        {
            this._frame = frame;

            this.noFrame = false;

            this.width = frame.width;
            this.height = frame.height;

            if (!this.trim && !this.rotate && (frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height))
            {
                throw new Error('Texture Error: frame does not fit inside the base Texture dimensions ' + this);
            }

            this.valid = frame && frame.width && frame.height && this.baseTexture.source && this.baseTexture.hasLoaded;

            if (this.trim)
            {

                this.width = this.trim.width;
                this.height = this.trim.height;
                this._frame.width = this.trim.width;
                this._frame.height = this.trim.height;
            }
            else
            {
                this.crop = frame;
            }

            if (this.valid)
            {
                this._updateUvs();
            }
        }
    }
});

/**
 * Updates this texture on the gpu.
 *
 */
Texture.prototype.update = function ()
{
    this.baseTexture.update();
};

/**
 * Called when the base texture is loaded
 *
 * @private
 */
Texture.prototype.onBaseTextureLoaded = function ()
{
    var baseTexture = this.baseTexture;
    baseTexture.removeEventListener('loaded', this.onLoaded);

    // TODO this code looks confusing.. boo to abusing getters and setterss!
    if (this.noFrame)
    {
        this.frame = new math.Rectangle(0, 0, baseTexture.width, baseTexture.height);
    }
    else
    {
        this.frame = this._frame;
    }

    this.dispatchEvent( { type: 'update', content: this } );
};

/**
 * Destroys this texture
 *
 * @param destroyBase {boolean} Whether to destroy the base texture as well
 */
Texture.prototype.destroy = function (destroyBase)
{
    if (destroyBase)
    {
        this.baseTexture.destroy();
    }

    this.valid = false;
};

/**
 * Updates the internal WebGL UV cache.
 *
 * @private
 */
Texture.prototype._updateUvs = function ()
{
    if (!this._uvs)
    {
        this._uvs = new TextureUvs();
    }

    this._uvs.set(this.crop, this.baseTexture, this.rotate);
};

/**
 * Helper function that creates a Texture object from the given image url.
 * If the image is not in the texture cache it will be  created and loaded.
 *
 * @static
 * @param imageUrl {string} The image url of the texture
 * @param crossorigin {boolean} Whether requests should be treated as crossorigin
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return Texture
 */
Texture.fromImage = function (imageUrl, crossorigin, scaleMode)
{
    var texture = utils.TextureCache[imageUrl];

    if (!texture)
    {
        texture = new Texture(BaseTexture.fromImage(imageUrl, crossorigin, scaleMode));
        utils.TextureCache[imageUrl] = texture;
    }

    return texture;
};

Texture.fromFrame = function (frameId)
{
    var texture = utils.TextureCache[frameId];

    if (!texture)
    {
        throw new Error('The frameId "' + frameId + '" does not exist in the texture cache' + this);
    }

    return texture;
};

/**
 * Helper function that creates a new Texture based on the given canvas element.
 *
 * @static
 * @param canvas {Canvas} The canvas element source of the texture
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return {Texture}
 */
Texture.fromCanvas = function (canvas, scaleMode)
{
    return new Texture(BaseTexture.fromCanvas(canvas, scaleMode));
};

/**
 * Helper function that creates a new Texture based on the given video element.
 *
 * @static
 * @param video {HTMLVideoElement}
 * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values
 * @return {Texture} A Texture
 */
Texture.fromVideo = function (video, scaleMode)
{
    return new Texture(VideoBaseTexture.baseTextureFromVideo(video, scaleMode));
};

/**
 * Adds a texture to the global utils.TextureCache. This cache is shared across the whole PIXI object.
 *
 * @static
 * @param texture {Texture} The Texture to add to the cache.
 * @param id {string} The id that the texture will be stored against.
 */
Texture.addTextureToCache = function (texture, id)
{
    utils.TextureCache[id] = texture;
};

/**
 * Remove a texture from the global utils.TextureCache.
 *
 * @static
 * @param id {string} The id of the texture to be removed
 * @return {Texture} The texture that was removed
 */
Texture.removeTextureFromCache = function (id)
{
    var texture = utils.TextureCache[id];

    delete utils.TextureCache[id];
    delete utils.BaseTextureCache[id];

    return texture;
};

Texture.emptyTexture = new Texture(new BaseTexture());
<|endoftext|>


<commit_before>import * as Preact from '#preact';
import {BentoFitText} from '../component';
import {number, text, withKnobs} from '@storybook/addon-knobs';

export default {
  title: 'BentoFitText',
  component: BentoFitText,
  decorators: [withKnobs],
};

export const _default = () => {
  const minFontSize = number('minFontSize', 35);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt.
    </BentoFitText>
  );
};

export const scaleUpOverflowEllipsis = () => {
  const minFontSize = number('minFontSize', 42);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt.
    </BentoFitText>
  );
};

export const scaleDown = () => {
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt. Propriae tincidunt id nec, elit nusquam te
      mea, ius noster platonem in. Mea an idque minim, sit sale deleniti
      apeirian et. Omnium legendos tractatos cu mea. Vix in stet dolorem
      accusamus. Iisque rationibus consetetur in cum, quo unum nulla legere ut.
      Simul numquam saperet no sit.
    </BentoFitText>
  );
};

export const scaleDownMore = () => {
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 108);
  const height = number('height', 78);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Superlongword text
    </BentoFitText>
  );
};

export const configureContent = () => {
  const content = text('Content', 'hello world');
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 200);
  const width = number('width', 400);
  const height = number('height', 400);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      {content}
    </BentoFitText>
  );
};
<commit_msg>BentoFitText title to 'FitText' (#35972)<commit_after>import * as Preact from '#preact';
import {BentoFitText} from '../component';
import {number, text, withKnobs} from '@storybook/addon-knobs';

export default {
  title: 'FitText',
  component: BentoFitText,
  decorators: [withKnobs],
};

export const _default = () => {
  const minFontSize = number('minFontSize', 35);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt.
    </BentoFitText>
  );
};

export const scaleUpOverflowEllipsis = () => {
  const minFontSize = number('minFontSize', 42);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt.
    </BentoFitText>
  );
};

export const scaleDown = () => {
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 300);
  const height = number('height', 200);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at
      aeque inermis reprehendunt. Propriae tincidunt id nec, elit nusquam te
      mea, ius noster platonem in. Mea an idque minim, sit sale deleniti
      apeirian et. Omnium legendos tractatos cu mea. Vix in stet dolorem
      accusamus. Iisque rationibus consetetur in cum, quo unum nulla legere ut.
      Simul numquam saperet no sit.
    </BentoFitText>
  );
};

export const scaleDownMore = () => {
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 72);
  const width = number('width', 108);
  const height = number('height', 78);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      Superlongword text
    </BentoFitText>
  );
};

export const configureContent = () => {
  const content = text('Content', 'hello world');
  const minFontSize = number('minFontSize', 6);
  const maxFontSize = number('maxFontSize', 200);
  const width = number('width', 400);
  const height = number('height', 400);
  return (
    <BentoFitText
      minFontSize={minFontSize}
      maxFontSize={maxFontSize}
      style={{border: '1px solid black', width, height}}
    >
      {content}
    </BentoFitText>
  );
};
<|endoftext|>


<commit_before>var search = function(body, request, url, callback) {

  request.get(url + '/hyperty/user/' + encodeURIComponent(body.resource), function(err, response, statusCode) {

    if(err) {
      var body = {
        'code': 504,
        'description': 'Error contacting the domain registry.'
      };
    }else if(statusCode == 200) {
      var body = {
        'code': statusCode,
        'value': response
      };
    }else {
      var body = {
        'code': statusCode,
        'description': response.message
      }
    }

    callback(body);
  });
};

var advancedSearch = function(body, request, url, callback) {
  var endpoint = '/hyperty/user/' + encodeURIComponent(body.resource) + '/hyperty';

  var resources = body.criteria.resources;
  var dataschemes = body.criteria.dataSchemes;

  var qsResources = '';
  var qsDataschemes = '';
  var querystring = '';

  if(typeof resources != "undefined" && resources != null && resources.length > 0) {
    var qsResources = 'resources=' + resources.join(',');
  }

  if(typeof dataschemes != "undefined" && dataschemes != null && dataschemes.length > 0) {
    var qsDataschemes = 'dataSchemes=' + dataschemes.join(',');
  }

  if(qsResources != "" && qsDataschemes != "") {
    var querystring = '?' + qsResources + '&' + qsDataschemes;
  }else if(qsResources != "") {
    var querystring = '?' + qsResources;
  }else if(qsDataschemes != "") {
    var querystring = '?' + qsDataschemes;
  }

  request.get(url + endpoint + querystring, function(err, response, statusCode) {
    if(err) {
      var body = {
        'code': 504,
        'description': 'Error contacting the domain registry.'
      };
    }else if(statusCode == 200) {
      var body = {
        'code': statusCode,
        'value': response
      };
    }else {
      var body = {
        'code': statusCode,
        'description': response.message
      }
    }

    callback(body);
  });

};

var hyperty = {
  read: function(body, request, url, isAdvanced, callback) {
    if(isAdvanced) {
      advancedSearch(body, request, url, callback);
    }else {
      search(body, request, url, callback);
    }
  },

  create: function(body, request, url, callback) {
    var endpoint = '/hyperty/user/' + encodeURIComponent(body.value.user) + '/' + encodeURIComponent(body.value.url);

    var data = {
      'descriptor': body.value.descriptor,
      'expires': body.value.expires,
      'resources': body.value.resources,
      'dataSchemes': body.value.dataSchemes,
      'status': body.value.status,
      'runtime': body.value.runtime,
      'p2pRequester': body.value.p2pRequester,
      'p2pHandler': body.value.p2pHandler
    };

    request.put(url + endpoint, data, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },

  update: function(body, request, url, callback) {

    var endpoint = '/hyperty/url/' + encodeURIComponent(body.resource);
    var data;

    if(typeof body.value != "undefined" && body.value != null) {
      data = {
        'descriptor': body.value.descriptor,
        'expires': body.value.expires,
        'resources': body.value.resources,
        'dataSchemes': body.value.dataSchemes,
        'status': body.value.status,
        'runtime': body.value.runtime,
        'p2pRequester': body.value.p2pRequester,
        'p2pHandler': body.value.p2pHandler
      };
    } else {
      data = {};
    }

    request.put(url + endpoint, data, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },

  del: function(body, request, url, callback) {
    var endpoint = '/hyperty/user/' + encodeURIComponent(body.value.user) + '/' + encodeURIComponent(body.value.url);

    request.del(url + endpoint, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },
};

module.exports = hyperty;
<commit_msg>Add support to 408 - Temporarily Unavailable hyperties.<commit_after>var search = function(body, request, url, callback) {

  request.get(url + '/hyperty/user/' + encodeURIComponent(body.resource), function(err, response, statusCode) {

    if(err) {
      var body = {
        'code': 504,
        'description': 'Error contacting the domain registry.'
      };
    }else if(statusCode == 200) {
      var body = {
        'code': statusCode,
        'value': response
      };
    }else if(statusCode == 408) {
      var body = {
        'code': statusCode,
        'description': 'Temporarily Unavailable',
        'value': response
      };
    }else {
      var body = {
        'code': statusCode,
        'description': response.message
      }
    }

    callback(body);
  });
};

var advancedSearch = function(body, request, url, callback) {
  var endpoint = '/hyperty/user/' + encodeURIComponent(body.resource) + '/hyperty';

  var resources = body.criteria.resources;
  var dataschemes = body.criteria.dataSchemes;

  var qsResources = '';
  var qsDataschemes = '';
  var querystring = '';

  if(typeof resources != "undefined" && resources != null && resources.length > 0) {
    var qsResources = 'resources=' + resources.join(',');
  }

  if(typeof dataschemes != "undefined" && dataschemes != null && dataschemes.length > 0) {
    var qsDataschemes = 'dataSchemes=' + dataschemes.join(',');
  }

  if(qsResources != "" && qsDataschemes != "") {
    var querystring = '?' + qsResources + '&' + qsDataschemes;
  }else if(qsResources != "") {
    var querystring = '?' + qsResources;
  }else if(qsDataschemes != "") {
    var querystring = '?' + qsDataschemes;
  }

  request.get(url + endpoint + querystring, function(err, response, statusCode) {
    if(err) {
      var body = {
        'code': 504,
        'description': 'Error contacting the domain registry.'
      };
    }else if(statusCode == 200) {
      var body = {
        'code': statusCode,
        'value': response
      };
    }else if(statusCode == 408) {
      var body = {
        'code': statusCode,
        'description': 'Temporarily Unavailable',
        'value': response
      };
    }else {
      var body = {
        'code': statusCode,
        'description': response.message
      }
    }

    callback(body);
  });

};

var hyperty = {
  read: function(body, request, url, isAdvanced, callback) {
    if(isAdvanced) {
      advancedSearch(body, request, url, callback);
    }else {
      search(body, request, url, callback);
    }
  },

  create: function(body, request, url, callback) {
    var endpoint = '/hyperty/user/' + encodeURIComponent(body.value.user) + '/' + encodeURIComponent(body.value.url);

    var data = {
      'descriptor': body.value.descriptor,
      'expires': body.value.expires,
      'resources': body.value.resources,
      'dataSchemes': body.value.dataSchemes,
      'status': body.value.status,
      'runtime': body.value.runtime,
      'p2pRequester': body.value.p2pRequester,
      'p2pHandler': body.value.p2pHandler
    };

    request.put(url + endpoint, data, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },

  update: function(body, request, url, callback) {

    var endpoint = '/hyperty/url/' + encodeURIComponent(body.resource);
    var data;

    if(typeof body.value != "undefined" && body.value != null) {
      data = {
        'descriptor': body.value.descriptor,
        'expires': body.value.expires,
        'resources': body.value.resources,
        'dataSchemes': body.value.dataSchemes,
        'status': body.value.status,
        'runtime': body.value.runtime,
        'p2pRequester': body.value.p2pRequester,
        'p2pHandler': body.value.p2pHandler
      };
    } else {
      data = {};
    }

    request.put(url + endpoint, data, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },

  del: function(body, request, url, callback) {
    var endpoint = '/hyperty/user/' + encodeURIComponent(body.value.user) + '/' + encodeURIComponent(body.value.url);

    request.del(url + endpoint, function(err, response, statusCode) {

      if(err) {
        var body = {
          'code': 504,
          'description': 'Error contacting the domain registry.'
        };
      }else {
        var body = {
          'code': statusCode
        };
      }

      callback(body);
    });

  },
};

module.exports = hyperty;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { BaseNode, interval } from 'kapellmeister'
import mergeKeys from '../core/mergeKeys'
import { ENTER, UPDATE, LEAVE } from '../core/types'

export default function createNodeGroup(getInterpolater, displayName = 'NodeGroup') {
  if (!getInterpolater) {
    throw new Error('[react-move] getInterpolator is required.')
  }

  class Node extends BaseNode {
    getInterpolator = getInterpolater
  }

  return class NodeGroup extends Component {
    static displayName = displayName

    static propTypes = {
      data: PropTypes.array.isRequired,
      keyAccessor: PropTypes.func.isRequired,
      start: PropTypes.func.isRequired,
      enter: PropTypes.func,
      update: PropTypes.func,
      leave: PropTypes.func,
      children: PropTypes.func.isRequired,
    }

    static defaultProps = {
      enter: () => {},
      update: () => {},
      leave: () => {},
    }

    state = {
      nodeKeys: [],
      nodeHash: {},
      nodes: [],
      data: null,
    }

    static getDerivedStateFromProps(nextProps, prevState) {
      if (nextProps.data !== prevState.data) {
        const { data, keyAccessor, start, enter, update, leave } = nextProps
        const { nodeKeys, nodeHash } = prevState

        const keyIndex = {}

        for (let i = 0; i < nodeKeys.length; i++) {
          keyIndex[nodeKeys[i]] = i
        }

        const nextKeyIndex = {}
        const nextNodeKeys = []

        for (let i = 0; i < data.length; i++) {
          const d = data[i]
          const k = keyAccessor(d, i)

          nextKeyIndex[k] = i
          nextNodeKeys.push(k)

          if (keyIndex[k] === undefined) {
            const node = new Node()
            node.key = k
            node.data = d
            node.type = ENTER
            nodeHash[k] = node
          }
        }

        for (let i = 0; i < nodeKeys.length; i++) {
          const k = nodeKeys[i]
          const n = nodeHash[k]

          if (nextKeyIndex[k] !== undefined) {
            n.data = data[nextKeyIndex[k]]
            n.type = UPDATE
          } else {
            n.type = LEAVE
          }
        }

        const mergedNodeKeys = mergeKeys(
          nodeKeys,
          keyIndex,
          nextNodeKeys,
          nextKeyIndex,
        )

        for (let i = 0; i < mergedNodeKeys.length; i++) {
          const k = mergedNodeKeys[i]
          const n = nodeHash[k]
          const d = n.data

          if (n.type === ENTER) {
            n.setState(start(d, nextKeyIndex[k]))
            n.transition(enter(d, nextKeyIndex[k]))
          } else if (n.type === LEAVE) {
            n.transition(leave(d, keyIndex[k]))
          } else {
            n.transition(update(d, nextKeyIndex[k]))
          }
        }

        return {
          data,
          nodes: mergedNodeKeys.map(key => {
            return nodeHash[key]
          }),
          nodeHash,
          nodeKeys: mergedNodeKeys,
        }
      }

      return null
    }

    componentDidMount() {
      this.startInterval()
    }

    componentDidUpdate(prevProps) {
      if (prevProps.data !== this.props.data && !this.unmounting) {
        this.startInterval()
      }
    }

    startInterval() {
      if (!this.interval) {
        this.interval = interval(this.animate)
      } else {
        this.interval.restart(this.animate)
      }
    }

    componentWillUnmount() {
      const { nodeKeys, nodeHash } = this.state

      this.unmounting = true

      if (this.interval) {
        this.interval.stop()
      }

      nodeKeys.forEach(key => {
        nodeHash[key].stopTransitions()
      })
    }

    animate = () => {
      const { nodeKeys, nodeHash } = this.state

      if (this.unmounting) {
        return
      }

      let pending = false

      const nextNodeKeys = []
      const length = nodeKeys.length

      for (let i = 0; i < length; i++) {
        const k = nodeKeys[i]
        const n = nodeHash[k]

        const isTransitioning = n.isTransitioning()

        if (isTransitioning) {
          pending = true
        }

        if (n.type === LEAVE && !isTransitioning) {
          delete nodeHash[k]
        } else {
          nextNodeKeys.push(k)
        }
      }

      if (!pending) {
        this.interval.stop()
      }

      this.setState(() => ({
        nodeKeys: nextNodeKeys,
        nodes: nextNodeKeys.map(key => {
          return nodeHash[key]
        }),
      }))
    }

    interval = null
    unmounting = false

    render() {
      const renderedChildren = this.props.children(this.state.nodes)
      return renderedChildren && React.Children.only(renderedChildren)
    }
  }
}
<commit_msg>check type of getInterpolator<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { BaseNode, interval } from 'kapellmeister'
import mergeKeys from '../core/mergeKeys'
import { ENTER, UPDATE, LEAVE } from '../core/types'

export default function createNodeGroup(getInterpolater, displayName = 'NodeGroup') {
  if (!getInterpolater || typeof getInterpolater !== 'function') {
    throw new Error('[react-move] getInterpolator function is required.')
  }

  class Node extends BaseNode {
    getInterpolator = getInterpolater
  }

  return class NodeGroup extends Component {
    static displayName = displayName

    static propTypes = {
      data: PropTypes.array.isRequired,
      keyAccessor: PropTypes.func.isRequired,
      start: PropTypes.func.isRequired,
      enter: PropTypes.func,
      update: PropTypes.func,
      leave: PropTypes.func,
      children: PropTypes.func.isRequired,
    }

    static defaultProps = {
      enter: () => {},
      update: () => {},
      leave: () => {},
    }

    state = {
      nodeKeys: [],
      nodeHash: {},
      nodes: [],
      data: null,
    }

    static getDerivedStateFromProps(nextProps, prevState) {
      if (nextProps.data !== prevState.data) {
        const { data, keyAccessor, start, enter, update, leave } = nextProps
        const { nodeKeys, nodeHash } = prevState

        const keyIndex = {}

        for (let i = 0; i < nodeKeys.length; i++) {
          keyIndex[nodeKeys[i]] = i
        }

        const nextKeyIndex = {}
        const nextNodeKeys = []

        for (let i = 0; i < data.length; i++) {
          const d = data[i]
          const k = keyAccessor(d, i)

          nextKeyIndex[k] = i
          nextNodeKeys.push(k)

          if (keyIndex[k] === undefined) {
            const node = new Node()
            node.key = k
            node.data = d
            node.type = ENTER
            nodeHash[k] = node
          }
        }

        for (let i = 0; i < nodeKeys.length; i++) {
          const k = nodeKeys[i]
          const n = nodeHash[k]

          if (nextKeyIndex[k] !== undefined) {
            n.data = data[nextKeyIndex[k]]
            n.type = UPDATE
          } else {
            n.type = LEAVE
          }
        }

        const mergedNodeKeys = mergeKeys(
          nodeKeys,
          keyIndex,
          nextNodeKeys,
          nextKeyIndex,
        )

        for (let i = 0; i < mergedNodeKeys.length; i++) {
          const k = mergedNodeKeys[i]
          const n = nodeHash[k]
          const d = n.data

          if (n.type === ENTER) {
            n.setState(start(d, nextKeyIndex[k]))
            n.transition(enter(d, nextKeyIndex[k]))
          } else if (n.type === LEAVE) {
            n.transition(leave(d, keyIndex[k]))
          } else {
            n.transition(update(d, nextKeyIndex[k]))
          }
        }

        return {
          data,
          nodes: mergedNodeKeys.map(key => {
            return nodeHash[key]
          }),
          nodeHash,
          nodeKeys: mergedNodeKeys,
        }
      }

      return null
    }

    componentDidMount() {
      this.startInterval()
    }

    componentDidUpdate(prevProps) {
      if (prevProps.data !== this.props.data && !this.unmounting) {
        this.startInterval()
      }
    }

    startInterval() {
      if (!this.interval) {
        this.interval = interval(this.animate)
      } else {
        this.interval.restart(this.animate)
      }
    }

    componentWillUnmount() {
      const { nodeKeys, nodeHash } = this.state

      this.unmounting = true

      if (this.interval) {
        this.interval.stop()
      }

      nodeKeys.forEach(key => {
        nodeHash[key].stopTransitions()
      })
    }

    animate = () => {
      const { nodeKeys, nodeHash } = this.state

      if (this.unmounting) {
        return
      }

      let pending = false

      const nextNodeKeys = []
      const length = nodeKeys.length

      for (let i = 0; i < length; i++) {
        const k = nodeKeys[i]
        const n = nodeHash[k]

        const isTransitioning = n.isTransitioning()

        if (isTransitioning) {
          pending = true
        }

        if (n.type === LEAVE && !isTransitioning) {
          delete nodeHash[k]
        } else {
          nextNodeKeys.push(k)
        }
      }

      if (!pending) {
        this.interval.stop()
      }

      this.setState(() => ({
        nodeKeys: nextNodeKeys,
        nodes: nextNodeKeys.map(key => {
          return nodeHash[key]
        }),
      }))
    }

    interval = null
    unmounting = false

    render() {
      const renderedChildren = this.props.children(this.state.nodes)
      return renderedChildren && React.Children.only(renderedChildren)
    }
  }
}
<|endoftext|>


<commit_before>function Pallet(canvas, options) {
	var self = this;

	options = options || {};

	if(typeof canvas == 'string') {
		canvas = document.getElementById(canvas.replace('#', ''));
	} else if(!canvas) {
		canvas = document.getElementsByTagName('canvas')[0];
		if(!canvas) return false;
	} else if(canvas.tagName != 'CANVAS') {
		return false;
	}

	var context = canvas.getContext('2d');

	this.canvas = canvas;
	this.context = context;

	context.webkitImageSmoothingEnabled = options.imageSmoothing || true;
	context.mozImageSmoothingEnabled = options.imageSmoothing || true;

	context.save();

	// Render single colour unstroked circle.
	this.circle = function(color, x, y, radius) {
		context.fillStyle = color;
		context.beginPath();
		context.arc(x, y, radius, 0, Math.PI * 2, false);
     	context.fill();
	};

	// Clear canvas.
	this.clear = function(x, y, w, h) {
		if(!h) {
			context.clearRect(0, 0, canvas.width, canvas.height);
		} else {
			context.clearRect(x, y, w, h);
		}
	};

	// Set canvas size to canvas element size.
	this.normalizeSize = function() {
		var style = window.getComputedStyle(canvas, null);

		canvas.width = +style.width.replace('px', '');
		canvas.height = +style.height.replace('px', '');

		context.save();
	};

	this.opacity = function(alpha) {
		alpha = alpha || 1;
		context.globalAlpha = alpha;
	};

	// Render single colour unstroked rectangle.
	this.rect = function(color, x, y, w, h) {
		context.fillStyle = color;
		context.fillRect(x, y, w, h);
	};

	// Restore canvas to original state.
	this.reset = function() {
		context.restore();
		context.save();
	};

	// Render rect with equal sides.
	this.square = function(color, x, y, l) {
		self.rect(color, x, y, l, l);
	};

	// Render text.
	this.text = function(string, x, y, color, font, size, align, baseline) {
		context.fillStyle = color || '#fff';
		if(+size == '' + size) size = size + 'px';
		context.font = size + ' ' + font;
		context.textAlign = align || 'left';
		context.textBaseline = baseline || 'top';
		context.fillText(string, x, y);
	};
}

<commit_msg>Add fill screen function<commit_after>function Pallet(canvas, options) {
	var self = this;

	options = options || {};

	if(typeof canvas == 'string') {
		canvas = document.getElementById(canvas.replace('#', ''));
	} else if(!canvas) {
		canvas = document.getElementsByTagName('canvas')[0];
		if(!canvas) return false;
	} else if(canvas.tagName != 'CANVAS') {
		return false;
	}

	var context = canvas.getContext('2d');

	this.canvas = canvas;
	this.context = context;

	context.webkitImageSmoothingEnabled = options.imageSmoothing || true;
	context.mozImageSmoothingEnabled = options.imageSmoothing || true;

	context.save();

	// Render single colour unstroked circle.
	this.circle = function(color, x, y, radius) {
		context.fillStyle = color;
		context.beginPath();
		context.arc(x, y, radius, 0, Math.PI * 2, false);
     	context.fill();
	};

	// Clear canvas.
	this.clear = function(x, y, w, h) {
		if(!h) {
			context.clearRect(0, 0, canvas.width, canvas.height);
		} else {
			context.clearRect(x, y, w, h);
		}
	};

	// Resize canvas to window.
	this.fillScreen = function() {
		canvas.width = window.innerWidth;
		canvas.height = window.innerHeight;
		canvas.style.width = canvas.width + 'px';
		canvas.style.height = canvas.height + 'px';

		self.normalizeSize();
	};

	// Set canvas size to canvas element size.
	this.normalizeSize = function() {
		var style = window.getComputedStyle(canvas, null);

		canvas.width = +style.width.replace('px', '');
		canvas.height = +style.height.replace('px', '');

		context.save();
	};

	this.opacity = function(alpha) {
		alpha = alpha || 1;
		context.globalAlpha = alpha;
	};

	// Render single colour unstroked rectangle.
	this.rect = function(color, x, y, w, h) {
		context.fillStyle = color;
		context.fillRect(x, y, w, h);
	};

	// Restore canvas to original state.
	this.reset = function() {
		context.restore();
		context.save();
	};

	// Render rect with equal sides.
	this.square = function(color, x, y, l) {
		self.rect(color, x, y, l, l);
	};

	// Render text.
	this.text = function(string, x, y, color, font, size, align, baseline) {
		context.fillStyle = color || '#fff';
		if(+size == '' + size) size = size + 'px';
		context.font = size + ' ' + font;
		context.textAlign = align || 'left';
		context.textBaseline = baseline || 'top';
		context.fillText(string, x, y);
	};
}

<|endoftext|>


<commit_before>import {
  GraphQLObjectType as ObjectType,
  GraphQLString as StringType,
  GraphQLNonNull as NonNull,
  GraphQLList,
  GraphQLID as ID,
} from 'graphql';
import StudyEntityType from './StudyEntityType';
import Course from '../models/Course';
import UserCourse from '../models/UserCourse';
import User from '../models/User';

const CourseType = new ObjectType({
  name: 'CourseType',
  fields: {
    id: { type: new NonNull(StringType) },
    title: { type: new NonNull(StringType) },
    studyEntities: {
      type: new GraphQLList(StudyEntityType),
      resolve: course => course.getStudyEntities(),
    },
    users: {
      type: new GraphQLList(
        new ObjectType({
          name: 'CourseUserType',
          fields: {
            id: { type: new NonNull(ID) },
            email: { type: StringType },
            role: { type: StringType },
          },
        }),
      ),
      resolve: course =>
        Course.find({
          where: { id: course.id },
          include: [{ model: User, as: 'user', through: UserCourse }],
        }).then(c =>
          c.user.map(user => ({
            id: user.id,
            email: user.email,
            role: user.UserCourse.role,
          })),
        ),
    },
  },
});

export default CourseType;
<commit_msg>fix retrievening users of course<commit_after>import {
  GraphQLObjectType as ObjectType,
  GraphQLString as StringType,
  GraphQLNonNull as NonNull,
  GraphQLList,
  GraphQLID as ID,
} from 'graphql';
import StudyEntityType from './StudyEntityType';
import Course from '../models/Course';
import UserCourse from '../models/UserCourse';
import User from '../models/User';

const CourseType = new ObjectType({
  name: 'CourseType',
  fields: {
    id: { type: new NonNull(StringType) },
    title: { type: new NonNull(StringType) },
    studyEntities: {
      type: new GraphQLList(StudyEntityType),
      resolve: course => course.getStudyEntities(),
    },
    users: {
      type: new GraphQLList(
        new ObjectType({
          name: 'CourseUserType',
          fields: {
            id: { type: new NonNull(ID) },
            email: { type: StringType },
            role: { type: StringType },
          },
        }),
      ),
      resolve: course =>
        Course.find({
          where: { id: course.id },
          include: [{ model: User, as: 'users', through: UserCourse }],
        }).then(c =>
          c.users.map(user => ({
            id: user.id,
            email: user.email,
            role: user.UserCourse.role,
          })),
        ),
    },
  },
});

export default CourseType;
<|endoftext|>


<commit_before>const BadRequestHttpException = Jymfony.Component.HttpFoundation.Exception.BadRequestHttpException;
const HttpExceptionInterface = Jymfony.Component.HttpFoundation.Exception.HttpExceptionInterface;
const NotFoundHttpException = Jymfony.Component.HttpFoundation.Exception.NotFoundHttpException;
const RequestExceptionInterface = Jymfony.Component.HttpFoundation.Exception.RequestExceptionInterface;
const ContentType = Jymfony.Component.HttpFoundation.Header.ContentType;
const Request = Jymfony.Component.HttpFoundation.Request;
const Response = Jymfony.Component.HttpFoundation.Response;
const Event = Jymfony.Component.HttpServer.Event;
const RequestParser = Jymfony.Component.HttpServer.RequestParser;

/**
 * @memberOf Jymfony.Component.HttpServer
 */
class HttpServer {
    /**
     * Constructor.
     *
     * @param {Jymfony.Component.EventDispatcher.EventDispatcherInterface} dispatcher
     * @param {Jymfony.Component.HttpFoundation.Controller.ControllerResolverInterface} resolver
     * @param {http.Server} http
     */
    __construct(dispatcher, resolver, http = require('http')) {
        /**
         * @type {Jymfony.Component.EventDispatcher.EventDispatcherInterface}
         * @protected
         */
        this._dispatcher = dispatcher;

        /**
         * @type {Jymfony.Component.HttpFoundation.Controller.ControllerResolverInterface}
         * @protected
         */
        this._resolver = resolver;

        /**
         * @type {http.Server}
         * @protected
         */
        this._http = new http.Server(this._incomingRequest.bind(this));
    }

    /**
     * Listen and handle connections.
     *
     * @returns {Promise<void>}
     */
    listen({ port = 80, host = '0.0.0.0', path = undefined } = {}) {
        return new Promise((resolve, reject) => {
            this._http.on('error', e => {
                this._http.removeAllListeners('close');
                this._http.close();

                reject(e);
            });

            this._http.on('close', resolve);

            if (!! path) {
                this._http.listen({ path });
            } else {
                this._http.listen({ host, port });
            }
        });
    }

    /**
     * Handles an incoming request from the http server.
     *
     * @param {IncomingMessage} req
     * @param {ServerResponse} res
     *
     * @private
     */
    _incomingRequest(req, res) {
        return __jymfony.Async
            .run(this._handleRequest(req, res))
            .catch(() => {
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.write('Unknown error while handling your request.\r\n');
                res.end();
            });
    }

    /**
     * Converts an IncomingMessage to an HttpFoundation request
     * and sends it to the Kernel.
     *
     * @param {IncomingMessage} req
     * @param {ServerResponse} res
     *
     * @protected
     */
    * _handleRequest(req, res) {
        const contentType = new ContentType(req.headers['content-type'] || 'application/x-www-form-urlencoded');
        let requestParams, content;

        try {
            [ requestParams, content ] = yield this._parseRequestContent(req, contentType);
        } catch (e) {
            if (e instanceof BadRequestException) {
                res.writeHead(400, {'Content-Type': 'text/plain'});
            } else {
                res.writeHead(500, {'Content-Type': 'text/plain'});
            }

            res.end();
            return;
        }

        const request = new Request(req.url, requestParams, {}, req.headers, {
            'REQUEST_METHOD': req.method,
            'REMOTE_ADDR': req.connection.remoteAddress,
            'SCHEME': this._getScheme(),
            'SERVER_PROTOCOL': 'HTTP/'+req.httpVersion,
        }, content);

        const response = yield this.handle(request);
        response.prepare(request);

        res.writeHead(response.statusCode, response.statusText, response.headers.all);
        yield new Promise((resolve) => {
            res.write(response.content, 'utf8', () => {
                resolve();
            });
        });

        res.end();
    }

    /**
     * Handles a Request to convert it to a Response.
     *
     * When catchExceptions is true, catches all exceptions
     * and do its best to convert them to a Response instance.
     *
     * @param {Jymfony.Component.HttpFoundation.Request} request A Request instance
     * @param {boolean} catchExceptions Whether to catch exceptions or not
     *
     * @returns {Jymfony.Component.HttpFoundation.Response} A Response instance
     *
     * @throws {Exception} When an Exception occurs during processing
     */
    * handle(request, catchExceptions = true) {
        let response;

        try {
            response = yield this._handleRaw(request);
        } catch (e) {
            if (e instanceof RequestExceptionInterface) {
                e = new BadRequestHttpException(e.message, e);
            }

            if (false === catchExceptions) {
                throw e;
            }

            response = yield this._handleException(e, request);
        }

        return response;
    }

    /**
     * Parse request content.
     *
     * @param {IncomingMessage} req
     * @param {Jymfony.Component.HttpFoundation.Header.ContentType} contentType
     *
     * @returns {Array} An array composed by the request params object
     *                  and the content as Buffer
     *
     * @protected
     */
    * _parseRequestContent(req, contentType) {
        const contentLength = ~~req.headers['content-length'] || undefined;

        let parser;
        if ('application/x-www-form-urlencoded' === contentType.essence) {
            parser = new RequestParser.UrlEncodedParser(req, contentLength);
        } else if ('application/json' === contentType.essence) {
            parser = new RequestParser.JsonEncodedParser(req, contentLength);
        } else if ('multipart' === contentType.type) {
            parser = new RequestParser.MultipartParser(req, contentType, contentLength);
        } else {
            parser = new RequestParser.OctetStreamParser(req, contentLength);
        }

        const params = yield parser.parse();

        return [ params, parser.buffer ];
    }

    /**
     * Dispatches request through the event dispatcher to obtain a valid response.
     *
     * @param {Jymfony.Component.HttpFoundation.Request} request
     *
     * @returns {Jymfony.Component.HttpFoundation.Response}
     *
     * @protected
     */
    * _handleRaw(request) {
        let event = new Event.GetResponseEvent(this, request);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.REQUEST, event);

        if (event.hasResponse()) {
            return yield this._filterResponse(event.response, request);
        }

        let controller = this._resolver.getController(request);
        if (false === controller) {
            throw new NotFoundHttpException(__jymfony.sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', request.pathInfo));
        }

        event = new Event.FilterControllerEvent(this, controller, request);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.CONTROLLER, event);
        controller = event.controller;

        const response = yield __jymfony.Async.run(controller, request);
        if (! (response instanceof Response)) {
            let msg = 'The controller must return a response.';

            // The user may have forgotten to return something
            if (undefined === response) {
                msg += ' Did you forget to add a return statement somewhere in your controller?';
            }

            throw new LogicException(msg);
        }

        return yield this._filterResponse(response, request);
    }

    /**
     * Handles an exception by trying to convert it to a Response.
     *
     * @param {Error} e An Error instance
     * @param {Jymfony.Component.HttpFoundation.Request} request A Request instance
     *
     * @protected
     */
    * _handleException(e, request) {
        const event = new Event.GetResponseForExceptionEvent(this, request, e);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.EXCEPTION, event);

        // A listener might have replaced the exception
        e = event.exception;
        if (! event.hasResponse()) {
            yield this._dispatcher.dispatch(Event.HttpServerEvents.FINISH_REQUEST, new Event.FinishRequestEvent(this, request));

            throw e;
        }

        const response = event.response;

        // The developer asked for a specific status code
        if (! event.isAllowingCustomResponseCode && ! response.isClientError && ! response.isServerError && ! response.isRedirect()) {
            // Ensure that we actually have an error response
            if (e instanceof HttpExceptionInterface) {
                // Keep the HTTP status code and headers
                response.setStatusCode(e.statusCode);
                response.headers.add(e.headers);
            } else {
                response.setStatusCode(500);
            }
        }

        try {
            return yield this._filterResponse(response, request);
        } catch (e) {
            return response;
        }
    }

    /**
     * Gets the request scheme.
     *
     * @return {string}
     *
     * @protected
     */
    _getScheme() {
        return 'http';
    }

    /**
     * Filters a response object.
     *
     * @param {Jymfony.Component.HttpFoundation.Response} response
     * @param {Jymfony.Component.HttpFoundation.Request} request
     *
     * @returns {Jymfony.Component.HttpFoundation.Response}
     *
     * @private
     */
    * _filterResponse(response, request) {
        const event = new Event.FilterResponseEvent(this, request, response);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.RESPONSE, event);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.FINISH_REQUEST, new Event.FinishRequestEvent(this, request));

        return event.response;
    }
}

module.exports = HttpServer;
<commit_msg>[HttpServer] do not wait for response write if has no content<commit_after>const BadRequestHttpException = Jymfony.Component.HttpFoundation.Exception.BadRequestHttpException;
const HttpExceptionInterface = Jymfony.Component.HttpFoundation.Exception.HttpExceptionInterface;
const NotFoundHttpException = Jymfony.Component.HttpFoundation.Exception.NotFoundHttpException;
const RequestExceptionInterface = Jymfony.Component.HttpFoundation.Exception.RequestExceptionInterface;
const ContentType = Jymfony.Component.HttpFoundation.Header.ContentType;
const Request = Jymfony.Component.HttpFoundation.Request;
const Response = Jymfony.Component.HttpFoundation.Response;
const Event = Jymfony.Component.HttpServer.Event;
const RequestParser = Jymfony.Component.HttpServer.RequestParser;

/**
 * @memberOf Jymfony.Component.HttpServer
 */
class HttpServer {
    /**
     * Constructor.
     *
     * @param {Jymfony.Component.EventDispatcher.EventDispatcherInterface} dispatcher
     * @param {Jymfony.Component.HttpFoundation.Controller.ControllerResolverInterface} resolver
     * @param {http.Server} http
     */
    __construct(dispatcher, resolver, http = require('http')) {
        /**
         * @type {Jymfony.Component.EventDispatcher.EventDispatcherInterface}
         * @protected
         */
        this._dispatcher = dispatcher;

        /**
         * @type {Jymfony.Component.HttpFoundation.Controller.ControllerResolverInterface}
         * @protected
         */
        this._resolver = resolver;

        /**
         * @type {http.Server}
         * @protected
         */
        this._http = new http.Server(this._incomingRequest.bind(this));
    }

    /**
     * Listen and handle connections.
     *
     * @returns {Promise<void>}
     */
    listen({ port = 80, host = '0.0.0.0', path = undefined } = {}) {
        return new Promise((resolve, reject) => {
            this._http.on('error', e => {
                this._http.removeAllListeners('close');
                this._http.close();

                reject(e);
            });

            this._http.on('close', resolve);

            if (!! path) {
                this._http.listen({ path });
            } else {
                this._http.listen({ host, port });
            }
        });
    }

    /**
     * Handles an incoming request from the http server.
     *
     * @param {IncomingMessage} req
     * @param {ServerResponse} res
     *
     * @private
     */
    _incomingRequest(req, res) {
        return __jymfony.Async
            .run(this._handleRequest(req, res))
            .catch(() => {
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.write('Unknown error while handling your request.\r\n');
                res.end();
            });
    }

    /**
     * Converts an IncomingMessage to an HttpFoundation request
     * and sends it to the Kernel.
     *
     * @param {IncomingMessage} req
     * @param {ServerResponse} res
     *
     * @protected
     */
    * _handleRequest(req, res) {
        const contentType = new ContentType(req.headers['content-type'] || 'application/x-www-form-urlencoded');
        let requestParams, content;

        try {
            [ requestParams, content ] = yield this._parseRequestContent(req, contentType);
        } catch (e) {
            if (e instanceof BadRequestException) {
                res.writeHead(400, {'Content-Type': 'text/plain'});
            } else {
                res.writeHead(500, {'Content-Type': 'text/plain'});
            }

            res.end();
            return;
        }

        const request = new Request(req.url, requestParams, {}, req.headers, {
            'REQUEST_METHOD': req.method,
            'REMOTE_ADDR': req.connection.remoteAddress,
            'SCHEME': this._getScheme(),
            'SERVER_PROTOCOL': 'HTTP/'+req.httpVersion,
        }, content);

        const response = yield this.handle(request);
        response.prepare(request);

        res.writeHead(response.statusCode, response.statusText, response.headers.all);

        if (! response.isEmpty && response.content) {
            yield new Promise((resolve) => {
                res.write(response.content, 'utf8', () => {
                    resolve();
                });
            });
        }

        res.end();
    }

    /**
     * Handles a Request to convert it to a Response.
     *
     * When catchExceptions is true, catches all exceptions
     * and do its best to convert them to a Response instance.
     *
     * @param {Jymfony.Component.HttpFoundation.Request} request A Request instance
     * @param {boolean} catchExceptions Whether to catch exceptions or not
     *
     * @returns {Jymfony.Component.HttpFoundation.Response} A Response instance
     *
     * @throws {Exception} When an Exception occurs during processing
     */
    * handle(request, catchExceptions = true) {
        let response;

        try {
            response = yield this._handleRaw(request);
        } catch (e) {
            if (e instanceof RequestExceptionInterface) {
                e = new BadRequestHttpException(e.message, e);
            }

            if (false === catchExceptions) {
                throw e;
            }

            response = yield this._handleException(e, request);
        }

        return response;
    }

    /**
     * Parse request content.
     *
     * @param {IncomingMessage} req
     * @param {Jymfony.Component.HttpFoundation.Header.ContentType} contentType
     *
     * @returns {Array} An array composed by the request params object
     *                  and the content as Buffer
     *
     * @protected
     */
    * _parseRequestContent(req, contentType) {
        const contentLength = ~~req.headers['content-length'] || undefined;

        let parser;
        if ('application/x-www-form-urlencoded' === contentType.essence) {
            parser = new RequestParser.UrlEncodedParser(req, contentLength);
        } else if ('application/json' === contentType.essence) {
            parser = new RequestParser.JsonEncodedParser(req, contentLength);
        } else if ('multipart' === contentType.type) {
            parser = new RequestParser.MultipartParser(req, contentType, contentLength);
        } else {
            parser = new RequestParser.OctetStreamParser(req, contentLength);
        }

        const params = yield parser.parse();

        return [ params, parser.buffer ];
    }

    /**
     * Dispatches request through the event dispatcher to obtain a valid response.
     *
     * @param {Jymfony.Component.HttpFoundation.Request} request
     *
     * @returns {Jymfony.Component.HttpFoundation.Response}
     *
     * @protected
     */
    * _handleRaw(request) {
        let event = new Event.GetResponseEvent(this, request);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.REQUEST, event);

        if (event.hasResponse()) {
            return yield this._filterResponse(event.response, request);
        }

        let controller = this._resolver.getController(request);
        if (false === controller) {
            throw new NotFoundHttpException(__jymfony.sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', request.pathInfo));
        }

        event = new Event.FilterControllerEvent(this, controller, request);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.CONTROLLER, event);
        controller = event.controller;

        const response = yield __jymfony.Async.run(controller, request);
        if (! (response instanceof Response)) {
            let msg = 'The controller must return a response.';

            // The user may have forgotten to return something
            if (undefined === response) {
                msg += ' Did you forget to add a return statement somewhere in your controller?';
            }

            throw new LogicException(msg);
        }

        return yield this._filterResponse(response, request);
    }

    /**
     * Handles an exception by trying to convert it to a Response.
     *
     * @param {Error} e An Error instance
     * @param {Jymfony.Component.HttpFoundation.Request} request A Request instance
     *
     * @protected
     */
    * _handleException(e, request) {
        const event = new Event.GetResponseForExceptionEvent(this, request, e);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.EXCEPTION, event);

        // A listener might have replaced the exception
        e = event.exception;
        if (! event.hasResponse()) {
            yield this._dispatcher.dispatch(Event.HttpServerEvents.FINISH_REQUEST, new Event.FinishRequestEvent(this, request));

            throw e;
        }

        const response = event.response;

        // The developer asked for a specific status code
        if (! event.isAllowingCustomResponseCode && ! response.isClientError && ! response.isServerError && ! response.isRedirect()) {
            // Ensure that we actually have an error response
            if (e instanceof HttpExceptionInterface) {
                // Keep the HTTP status code and headers
                response.setStatusCode(e.statusCode);
                response.headers.add(e.headers);
            } else {
                response.setStatusCode(500);
            }
        }

        try {
            return yield this._filterResponse(response, request);
        } catch (e) {
            return response;
        }
    }

    /**
     * Gets the request scheme.
     *
     * @return {string}
     *
     * @protected
     */
    _getScheme() {
        return 'http';
    }

    /**
     * Filters a response object.
     *
     * @param {Jymfony.Component.HttpFoundation.Response} response
     * @param {Jymfony.Component.HttpFoundation.Request} request
     *
     * @returns {Jymfony.Component.HttpFoundation.Response}
     *
     * @private
     */
    * _filterResponse(response, request) {
        const event = new Event.FilterResponseEvent(this, request, response);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.RESPONSE, event);
        yield this._dispatcher.dispatch(Event.HttpServerEvents.FINISH_REQUEST, new Event.FinishRequestEvent(this, request));

        return event.response;
    }
}

module.exports = HttpServer;
<|endoftext|>


<commit_before>/*!
 * uki JavaScript Library v0.0.1
 * Licensed under the MIT license
 *
 * Copyright (c) 2009 Vladimir Kolesnikov
 *
 * Parts of code derived from jQuery JavaScript Library v1.3.2
 * Copyright (c) 2009 John Resig
 */
(function() {
include('uki-core/const.js');
include('uki-core/uki.js');
include('uki-core/utils.js');
include('uki-core/geometry.js');
include('uki-core/builder.js');
include('uki-core/selector.js');

include('uki-core/dom.js');
include('uki-core/dom/event.js');
include('uki-core/dom/offset.js');
include('uki-core/dom/drag.js');
include('uki-core/dom/nativeLayout.js');

include('uki-core/attachment.js');
include('uki-core/image.js');

include('uki-core/background.js');
include('uki-core/background/null.js');
include('uki-core/background/sliced9.js');
include('uki-core/background/css.js');
include('uki-core/background/cssBox.js');
include('uki-core/background/rows.js');

include('uki-core/theme.js');
include('uki-core/theme/base.js');
include('uki-core/theme/template.js');

include('uki-core/view/utils.js');
include('uki-core/view/cssable.js');
include('uki-core/view/observable.js');
include('uki-core/view/focusable.js');
include('uki-core/view/base.js');
include('uki-core/view/container.js');

include('uki-view/view/box.js');
include('uki-view/view/image.js');
include('uki-view/view/button.js');
include('uki-view/view/checkbox.js');
include('uki-view/view/radio.js');
include('uki-view/view/textField.js');
include('uki-view/view/label.js');
include('uki-view/view/list.js');
include('uki-view/view/table.js');
include('uki-view/view/slider.js');
include('uki-view/view/splitPane.js');
include('uki-view/view/scrollPane.js');
include('uki-view/view/popup.js');
include('uki-view/view/flow.js');
include('uki-view/view/toolbar.js');
}());<commit_msg>error in version<commit_after>/*!
 * uki JavaScript Library
 * Licensed under the MIT license
 *
 * Copyright (c) 2009 Vladimir Kolesnikov
 *
 * Parts of code derived from jQuery JavaScript Library v1.3.2
 * Copyright (c) 2009 John Resig
 */
(function() {
include('uki-core/const.js');
include('uki-core/uki.js');
include('uki-core/utils.js');
include('uki-core/geometry.js');
include('uki-core/builder.js');
include('uki-core/selector.js');

include('uki-core/dom.js');
include('uki-core/dom/event.js');
include('uki-core/dom/offset.js');
include('uki-core/dom/drag.js');
include('uki-core/dom/nativeLayout.js');

include('uki-core/attachment.js');
include('uki-core/image.js');

include('uki-core/background.js');
include('uki-core/background/null.js');
include('uki-core/background/sliced9.js');
include('uki-core/background/css.js');
include('uki-core/background/cssBox.js');
include('uki-core/background/rows.js');

include('uki-core/theme.js');
include('uki-core/theme/base.js');
include('uki-core/theme/template.js');

include('uki-core/view/utils.js');
include('uki-core/view/cssable.js');
include('uki-core/view/observable.js');
include('uki-core/view/focusable.js');
include('uki-core/view/base.js');
include('uki-core/view/container.js');

include('uki-view/view/box.js');
include('uki-view/view/image.js');
include('uki-view/view/button.js');
include('uki-view/view/checkbox.js');
include('uki-view/view/radio.js');
include('uki-view/view/textField.js');
include('uki-view/view/label.js');
include('uki-view/view/list.js');
include('uki-view/view/table.js');
include('uki-view/view/slider.js');
include('uki-view/view/splitPane.js');
include('uki-view/view/scrollPane.js');
include('uki-view/view/popup.js');
include('uki-view/view/flow.js');
include('uki-view/view/toolbar.js');
}());<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'

import UltraSelect from './UltraSelect'

import './DatePicker.less'

function daysInMonth(year, month) {
    return new Date(year, month, 0).getDate()
}

function padStart(num) {
    return num >= 10 ? num.toString() : `0${num}`
}

const localeConfigs = {
    en: {
        order: ['month', 'date', 'year', 'hour', 'minute', 'ampm'],
        year: year => year,
        month: month => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][month],
        date: date => date,
        am: 'AM',
        pm: 'PM',
        hour: (hour, use24hours) => use24hours ? padStart(hour) : (hour === 0 ? '12' : padStart(hour)),
        minute: minute => padStart(minute),
        confirmButton: 'CONFIRM',
    }
}

class DatePicker extends Component {
    static propTypes = {
        max: PropTypes.string,
        min: PropTypes.string,
        defaultDate: PropTypes.string,
        type: PropTypes.oneOf(['date', 'datetime', 'time', 'month']),
        locale: PropTypes.oneOf(['en', 'zh-cn', 'zh-tw']),
        use24hours: PropTypes.bool,
        onSelect: PropTypes.func,
        onDidSelect: PropTypes.func,
    }

    static defaultProps = {
        min: '1950-01-01',
        max: '2049-12-31',
        type: 'date',
        locale: 'en',
        use24hours: false,
    }

    constructor(props) {
        super(props)
        this.onSelect = this.onSelect.bind(this)
        this.onDidSelect = this.onDidSelect.bind(this)

        this.state = this.calColumnsAndKeys(this.getDefaults(props))
    }

    getDefaults(props) {
        props = props || this.props
        let defaultDate = props.defaultDate ? new Date(props.defaultDate) : new Date()
        return {
            year: defaultDate.getFullYear(),
            month: defaultDate.getMonth() + 1,
            date: props.defaultDate ? defaultDate.getDate() : 1,
            ampm: defaultDate.getHours() >= 12 ? 'pm' : 'am',
            hour: defaultDate.getHours(),
            minute: defaultDate.getMinutes(),
        }
    }

    getValueFromState(key, defaultIndex) {
        let state = this.state
        let columnIndex = state.keys.findIndex(e => e === key)
        defaultIndex = typeof defaultIndex === 'number' ? defaultIndex : state.columns[columnIndex].defaultIndex
        return state.columns[columnIndex].list[defaultIndex].key
    }

    calColumnsAndKeys(defaults) {
        const {type, use24hours, min, max, locale} = this.props
        // 1. select keys
        let selectedKeys
        switch (type) {
            case 'date':
                selectedKeys = ['year', 'month', 'date']
                break
            case 'datetime':
                if (use24hours) {
                    selectedKeys = ['year', 'month', 'date', 'hour', 'minute']
                }
                else {
                    selectedKeys = ['year', 'month', 'date', 'ampm', 'hour', 'minute']
                }
                break
            case 'time':
                if (use24hours) {
                    selectedKeys = ['hour', 'minute']
                }
                else {
                    selectedKeys = ['ampm', 'hour', 'minute']
                }
                break
            case 'month':
                selectedKeys = ['year', 'month']
                break
        }
        // 2. calculate range
        let columnsDict = {}
        let reg = /\d{1,2}:\d{1,2}$/
        let minDate = new Date(`${min} ${min.match(reg) ? '' : '00:00'}`)
        let maxDate = new Date(`${max} ${max.match(reg) ? '' : '23:59'}`)
        for (let i = 0, l = selectedKeys.length; i < l; i++) {
            switch (selectedKeys[i]) {
                case 'year':
                    columnsDict[selectedKeys[i]] = this.calYear(minDate, maxDate, defaults)
                    break
                case 'month':
                    columnsDict[selectedKeys[i]] = this.calMonth(minDate, maxDate, defaults)
                    break
                case 'date':
                    columnsDict[selectedKeys[i]] = this.calDate(minDate, maxDate, defaults)
                    break
                case 'ampm':
                    columnsDict[selectedKeys[i]] = this.calAMPM(minDate, maxDate, defaults)
                    break
                case 'hour':
                    columnsDict[selectedKeys[i]] = this.calHour(minDate, maxDate, defaults)
                    break
                case 'minute':
                    columnsDict[selectedKeys[i]] = this.calMinute(minDate, maxDate, defaults)
                    break
            }
        }
        // 3. order columns
        let config = localeConfigs[locale]
        let columns = []
        let keys = []
        for (let i = 0, l = config.order.length; i < l; i++) {
            if (columnsDict[config.order[i]]) {
                columns.push(columnsDict[config.order[i]])
                keys.push(config.order[i])
            }
        }
        return {
            keys,
            columns
        }
    }

    get date() {
        let defaults = this.getDefaults()
        for (let i = 0, l = this.state.keys.length; i < l; i++) {
            let key = this.state.keys[i]
            defaults[key] = this.getValueFromState(key, null)
        }
        let hour = defaults.hour % 12
        if (defaults.ampm === 'pm') hour += 12
        return new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hour}:${defaults.minute}`)
    }

    onSelect(index, selectedValue) {
        let defaults = this.getDefaults()
        let newIndex = this.state.columns[index].list.findIndex(e => e.key === selectedValue.key)
        for (let i = 0, l = this.state.keys.length; i < l; i++) {
            let key = this.state.keys[i]
            defaults[key] = this.getValueFromState(key, i === index ? newIndex : null)
        }
        this.setState(this.calColumnsAndKeys(defaults))

        if (this.props.onSelect) {
            this.props.onSelect(this.date)
        }
    }

    onDidSelect(index, selectedValue) {
        if (this.props.onDidSelect) {
            this.props.onDidSelect(this.date)
        }
    }

    calYear(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = min.getFullYear(), l = max.getFullYear(), index = 0; i <= l; i++, index++) {
            ret.list.push({
                key: i,
                value: localeConfigs[this.props.locale].year(i)
            })
            if (i === defaults.year) {
                ret.defaultIndex = index
            }
        }
        ret.defaultIndex = (ret.defaultIndex === -1) ? ret.list.length - 1 : ret.defaultIndex
        return ret
    }

    calMonth(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = 1, index = 0; i <= 12; i++, index++) {
            let d = new Date(`${defaults.year}-${i}-1`)
            if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].month(i - 1)
                })
                if (i === defaults.month) {
                    ret.defaultIndex = index
                }
            }
        }
        ret.defaultIndex = (ret.defaultIndex === -1) ? ret.list.length - 1 : ret.defaultIndex
        return ret
    }

    calDate(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let days = daysInMonth(defaults.year, defaults.month)
        for (let i = 1, index = 0; i <= days; i++, index++) {
            let d = new Date(`${defaults.year}-${defaults.month}-${i}`)
            if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].date(i)
                })
                if (i === defaults.date) {
                    ret.defaultIndex = index
                }
            }
        }
        ret.defaultIndex = (ret.defaultIndex === -1) ? ret.list.length - 1 : ret.defaultIndex
        return ret
    }

    calAMPM(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let hour = defaults.hour % 12
        let index = 0
        let d = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hour}:${defaults.minute}`)
        if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
            ret.list.push({
                key: 'am',
                value: localeConfigs[this.props.locale].am
            })
            if (defaults.ampm === 'am') {
                ret.defaultIndex = index
            }
            index++
        }
        d = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hour+12}:${defaults.minute}`)
        if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
            ret.list.push({
                key: 'pm',
                value: localeConfigs[this.props.locale].pm
            })
            if (defaults.ampm === 'pm') {
                ret.defaultIndex = index
            }
        }
        return ret
    }

    calHour(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let start, end
        if (this.props.use24hours) {
            start = 0
            end = 23
        }
        else {
            start = 0
            end = 11
        }
        for (let i = start, index = 0; i <= end; i++, index++) {
            let hours = (!this.props.use24hours && defaults.ampm === 'pm') ? i+12 : i
            let d = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hours}:00`)
            if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].hour(i, this.props.use24hours)
                })
                if (i === defaults.hour) {
                    ret.defaultIndex = index
                }
            }
        }
        ret.defaultIndex = (ret.defaultIndex === -1) ? ret.list.length - 1 : ret.defaultIndex
        return ret
    }

    calMinute(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = 0; i < 60; i++) {
            let d = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${defaults.hour}:${i}`)
            if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].minute(i)
                })
                if (i === defaults.minute) {
                    ret.defaultIndex = i
                }
            }
        }
        ret.defaultIndex = (ret.defaultIndex === -1) ? ret.list.length - 1 : ret.defaultIndex
        return ret
    }

    render() {
        let copyColumns = [], columns = this.state.columns
        for (let i = 0, l = columns.length; i < l; i++) {
            copyColumns.push({list: [...columns[i].list], defaultIndex: columns[i].defaultIndex})
        }
        return <UltraSelect columns={copyColumns} onSelect={this.onSelect} onDidSelect={this.onDidSelect}
                    confirmButton={localeConfigs[this.props.locale].confirmButton}></UltraSelect>
    }
}

export default DatePicker
<commit_msg>fix min and max date range<commit_after>import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'

import UltraSelect from './UltraSelect'

import './DatePicker.less'

function daysInMonth(year, month) {
    return new Date(year, month, 0).getDate()
}

function padStart(num) {
    return num >= 10 ? num.toString() : `0${num}`
}

const localeConfigs = {
    'en': {
        order: ['month', 'date', 'year', 'hour', 'minute', 'ampm'],
        year: year => year,
        month: month => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][month],
        date: date => date,
        am: 'AM',
        pm: 'PM',
        hour: (hour, use24hours) => use24hours ? padStart(hour) : (hour === 0 ? '12' : padStart(hour)),
        minute: minute => padStart(minute),
        confirmButton: 'CONFIRM',
    },
    'zh-cn': {
        order: ['year', 'month', 'date', 'ampm', 'hour', 'minute'],
        year: year => `${year}年`,
        month: month => `${month+1}月`,
        date: date => `${date}日`,
        am: '上午',
        pm: '下午',
        hour: (hour, use24hours) => use24hours ? padStart(hour) : (hour === 0 ? '12' : padStart(hour)),
        minute: minute => padStart(minute),
        confirmButton: '确定',
    },
}

// to keep this library size small, expose a function to expand localeConfigs on demand
export const addLocaleConfig = (key, config) => {
    localeConfigs[key] = config
}

class DatePicker extends Component {
    static propTypes = {
        max: PropTypes.string,
        min: PropTypes.string,
        defaultDate: PropTypes.string,
        type: PropTypes.oneOf(['date', 'datetime', 'time', 'month']),
        locale: PropTypes.oneOf(['en', 'zh-cn']),
        use24hours: PropTypes.bool,
        onSelect: PropTypes.func,
        onDidSelect: PropTypes.func,
        getTitle: PropTypes.func,
        getStaticText: PropTypes.func,
    }

    static defaultProps = {
        min: '1950-01-01',
        max: '2049-12-31',
        type: 'date',
        locale: 'en',
        use24hours: false,
    }

    constructor(props) {
        super(props)
        this.onSelect = this.onSelect.bind(this)
        this.onDidSelect = this.onDidSelect.bind(this)

        this.state = this.calColumnsAndKeys(this.getDefaults(props))
    }

    getDefaults(props) {
        props = props || this.props
        let defaultDate = props.defaultDate ? new Date(props.defaultDate) : new Date()
        return {
            year: defaultDate.getFullYear(),
            month: defaultDate.getMonth() + 1,
            date: props.defaultDate ? defaultDate.getDate() : 1,
            ampm: defaultDate.getHours() >= 12 ? 'pm' : 'am',
            hour: defaultDate.getHours(),
            minute: defaultDate.getMinutes(),
        }
    }

    getValueFromState(key, defaultIndex) {
        let state = this.state
        let columnIndex = state.keys.findIndex(e => e === key)
        defaultIndex = typeof defaultIndex === 'number' ? defaultIndex : state.columns[columnIndex].defaultIndex
        return state.columns[columnIndex].list[defaultIndex].key
    }

    calColumnsAndKeys(defaults) {
        const {type, use24hours, min, max, locale} = this.props
        // 1. select keys
        // WARNING: keys in selectedKeys should be arranged in order to ensure DatePicker work properly
        // year -> month -> date -> ampm -> hour -> minute
        // that is, from bigger scope to smaller scope
        let selectedKeys
        switch (type) {
            case 'date':
                selectedKeys = ['year', 'month', 'date']
                break
            case 'datetime':
                if (use24hours) {
                    selectedKeys = ['year', 'month', 'date', 'hour', 'minute']
                }
                else {
                    selectedKeys = ['year', 'month', 'date', 'ampm', 'hour', 'minute']
                }
                break
            case 'time':
                if (use24hours) {
                    selectedKeys = ['hour', 'minute']
                }
                else {
                    selectedKeys = ['ampm', 'hour', 'minute']
                }
                break
            case 'month':
                selectedKeys = ['year', 'month']
                break
        }
        // 2. calculate range
        let columnsDict = {}
        let reg = /\d{1,2}:\d{1,2}$/
        let minDate = new Date(`${min} ${min.match(reg) ? '' : '00:00'}`)
        let maxDate = new Date(`${max} ${max.match(reg) ? '' : '23:59'}`)
        for (let i = 0, l = selectedKeys.length; i < l; i++) {
            switch (selectedKeys[i]) {
                case 'year':
                    columnsDict[selectedKeys[i]] = this.calYear(minDate, maxDate, defaults)
                    break
                case 'month':
                    columnsDict[selectedKeys[i]] = this.calMonth(minDate, maxDate, defaults)
                    break
                case 'date':
                    columnsDict[selectedKeys[i]] = this.calDate(minDate, maxDate, defaults)
                    break
                case 'ampm':
                    columnsDict[selectedKeys[i]] = this.calAMPM(minDate, maxDate, defaults)
                    break
                case 'hour':
                    columnsDict[selectedKeys[i]] = this.calHour(minDate, maxDate, defaults)
                    break
                case 'minute':
                    columnsDict[selectedKeys[i]] = this.calMinute(minDate, maxDate, defaults)
                    break
            }
        }
        // 3. order columns
        let config = localeConfigs[locale]
        let columns = []
        let keys = []
        for (let i = 0, l = config.order.length; i < l; i++) {
            if (columnsDict[config.order[i]]) {
                columns.push(columnsDict[config.order[i]])
                keys.push(config.order[i])
            }
        }
        return {
            keys,
            columns
        }
    }

    get date() {
        let defaults = this.getDefaults()
        for (let i = 0, l = this.state.keys.length; i < l; i++) {
            let key = this.state.keys[i]
            defaults[key] = this.getValueFromState(key, null)
        }
        let hour = defaults.hour % 12
        if (defaults.ampm === 'pm') hour += 12
        return new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hour}:${defaults.minute}`)
    }

    onSelect(index, selectedValue) {
        let defaults = this.getDefaults()
        let newIndex = this.state.columns[index].list.findIndex(e => e.key === selectedValue.key)
        for (let i = 0, l = this.state.keys.length; i < l; i++) {
            let key = this.state.keys[i]
            defaults[key] = this.getValueFromState(key, i === index ? newIndex : null)
        }
        this.setState(this.calColumnsAndKeys(defaults))

        if (this.props.onSelect) {
            this.props.onSelect(this.date)
        }
    }

    onDidSelect(index, selectedValue) {
        if (this.props.onDidSelect) {
            this.props.onDidSelect(this.date)
        }
    }

    inDateRange(d, min, max) {
        return d.getTime() >= min.getTime() && d.getTime() <= max.getTime()
    }

    calYear(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = min.getFullYear(), l = max.getFullYear(), index = 0; i <= l; i++, index++) {
            ret.list.push({
                key: i,
                value: localeConfigs[this.props.locale].year(i)
            })
            if (i === defaults.year) {
                ret.defaultIndex = index
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.year = ret.list[ret.defaultIndex].key
        return ret
    }

    calMonth(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = 1, index = 0; i <= 12; i++) {
            let dMin = new Date(`${defaults.year}-${i}-1 00:00`)
            let dMax = new Date(`${defaults.year}-${i}-${daysInMonth(defaults.year, i)} 23:59`)
            if (this.inDateRange(dMin, min, max) || this.inDateRange(dMax, min, max)) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].month(i - 1)
                })
                if (i === defaults.month) {
                    ret.defaultIndex = index
                }
                index++
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.month = ret.list[ret.defaultIndex].key
        return ret
    }

    calDate(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let days = daysInMonth(defaults.year, defaults.month)
        for (let i = 1, index = 0; i <= days; i++) {
            let dMin = new Date(`${defaults.year}-${defaults.month}-${i} 00:00`)
            let dMax = new Date(`${defaults.year}-${defaults.month}-${i} 23:59`)
            if (this.inDateRange(dMin, min, max) || this.inDateRange(dMax, min, max)) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].date(i)
                })
                if (i === defaults.date) {
                    ret.defaultIndex = index
                }
                index++
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.date = ret.list[ret.defaultIndex].key
        return ret
    }

    calAMPM(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let hour = defaults.hour % 12
        let index = 0
        let dMin = new Date(`${defaults.year}-${defaults.month}-${defaults.date} 00:00`)
        let dMax = new Date(`${defaults.year}-${defaults.month}-${defaults.date} 11:59`)
        if (this.inDateRange(dMin, min, max) || this.inDateRange(dMax, min, max)) {
            ret.list.push({
                key: 'am',
                value: localeConfigs[this.props.locale].am
            })
            if (defaults.ampm === 'am') {
                ret.defaultIndex = index
            }
            index++
        }
        dMin = new Date(`${defaults.year}-${defaults.month}-${defaults.date} 12:00`)
        dMax = new Date(`${defaults.year}-${defaults.month}-${defaults.date} 23:59`)
        if (this.inDateRange(dMin, min, max) || this.inDateRange(dMax, min, max)) {
            ret.list.push({
                key: 'pm',
                value: localeConfigs[this.props.locale].pm
            })
            if (defaults.ampm === 'pm') {
                ret.defaultIndex = index
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.ampm = ret.list[ret.defaultIndex].key
        return ret
    }

    calHour(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        let start, end
        if (this.props.use24hours) {
            start = 0
            end = 23
        }
        else {
            start = 0
            end = 11
        }
        for (let i = start, index = 0; i <= end; i++) {
            let hours = i
            if (!this.props.use24hours) {
                hours %= 12
                if (defaults.ampm === 'pm') hours += 12
            }
            let dMin = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hours}:00`)
            let dMax = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hours}:59`)
            if (this.inDateRange(dMin, min, max) || this.inDateRange(dMax, min, max)) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].hour(i, this.props.use24hours)
                })
                if (i === defaults.hour) {
                    ret.defaultIndex = index
                }
                index++
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.hour = ret.list[ret.defaultIndex].key
        return ret
    }

    calMinute(min, max, defaults) {
        let ret = {list:[], defaultIndex:-1}
        for (let i = 0, index = 0; i < 60; i++) {
            let hours = defaults.hour
            if (!this.props.use24hours) {
                hours %= 12
                if (defaults.ampm === 'pm') hours += 12
            }
            let d = new Date(`${defaults.year}-${defaults.month}-${defaults.date} ${hours}:${i}`)
            if (d.getTime() >= min.getTime() && d.getTime() <= max.getTime()) {
                ret.list.push({
                    key: i,
                    value: localeConfigs[this.props.locale].minute(i)
                })
                if (i === defaults.minute) {
                    ret.defaultIndex = index
                }
                index++
            }
        }
        if (ret.defaultIndex === -1) ret.defaultIndex = ret.list.length - 1
        if (ret.list.length > 0) defaults.minute = ret.list[ret.defaultIndex].key
        return ret
    }

    render() {
        let copyColumns = [], columns = this.state.columns
        for (let i = 0, l = columns.length; i < l; i++) {
            copyColumns.push({list: [...columns[i].list], defaultIndex: columns[i].defaultIndex})
        }
        return <UltraSelect columns={copyColumns}
                            onSelect={this.onSelect}
                            onDidSelect={this.onDidSelect}
                            confirmButton={localeConfigs[this.props.locale].confirmButton}
                            getTitle={this.props.getTitle}
                            getStaticText={this.props.getStaticText}
        ></UltraSelect>
    }
}

export default DatePicker
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { createStyleSheet } from 'stylishly';
import Paper from 'material-ui/Paper';

const styleSheet = createStyleSheet('FlatButtons', (theme) => {
  return {
    root: theme.mixins.gutters({
      paddingTop: 5,
      paddingBottom: 5,
    }),
  };
});

export default function PaperSheet(props, context) {
  const classes = context.styleManager.render(styleSheet);
  return (

      <Paper className={classes.root} zDepth={4}>

This is a sheet of paper.

          Paper can be used to build surface or other elements for your application.

      </Paper>

  );
}

PaperSheet.contextTypes = {
  styleManager: PropTypes.object.isRequired,
};
<commit_msg>Fix paper stylesheet name in docs<commit_after>import React, { PropTypes } from 'react';
import { createStyleSheet } from 'stylishly';
import Paper from 'material-ui/Paper';

const styleSheet = createStyleSheet('PaperSheet', (theme) => {
  return {
    root: theme.mixins.gutters({
      paddingTop: 5,
      paddingBottom: 5,
    }),
  };
});

export default function PaperSheet(props, context) {
  const classes = context.styleManager.render(styleSheet);
  return (

      <Paper className={classes.root} zDepth={4}>

This is a sheet of paper.

          Paper can be used to build surface or other elements for your application.

      </Paper>

  );
}

PaperSheet.contextTypes = {
  styleManager: PropTypes.object.isRequired,
};
<|endoftext|>