<commit_before>/**
  * @constructor
  * @extends ViewBase
  * @see DOM_tree_style this class can be dynamically exchanged with DOM_tree_style
  */

var DOM_markup_style = function(id, name, container_class)
{
  var self = this;

  const
  ID = 0,
  TYPE = 1,
  NAME = 2,
  DEPTH = 3,
  NAMESPACE = 4,
  VALUE = 7,
  ATTRS = 5,
  ATTR_PREFIX = 0,
  ATTR_KEY = 1,
  ATTR_VALUE = 2,
  CHILDREN_LENGTH = 6,
  PUBLIC_ID = 8,
  SYSTEM_ID = 9,
  INDENT = "  ",
  LINEBREAK = '\n';

  var getIndent = function(count)
  {
    var ret = '';
    if(count)
    {
      count--;
    }
    while(count)
    {
      ret += INDENT;
      count--;
    }
    return ret;
  };

  var div_padding_value = 0;

  var spotlightElement = function()
  {
    hostspotlighter.spotlight(parseInt(this.getAttribute('ref-id')));
  }

  var clearSpotlightElement = function()
  {
    hostspotlighter.clearSpotlight();
  }

  this.updateTarget = function(ele, obj_id)
  {
    if(ele)
    {
      var target = document.getElementById('target-element');
      if(target)
      {
        target.removeAttribute('id');
        target.removeEventListener('mouseover', spotlightElement, false);
        target.removeEventListener('mouseout', clearSpotlightElement, false);
      }
      if(/<\//.test(ele.firstChild.nodeValue))
      {
        while( ( ele = ele.previousSibling ) && ele.getAttribute('ref-id') != obj_id );
      }
      topCell.statusbar.updateInfo
      (
        // the same template is used with inner html
        templates.breadcrumb(dom_data.getCSSPath()).
          concat(['onmouseover', helpers.breadcrumbSpotlight,
                  'onmouseout', helpers.breadcrumbClearSpotlight])
      );
    }
    if(ele || ( ele = document.getElementById('target-element') ) )
    {
      ele.id = 'target-element';
      ele.addEventListener('mouseover', spotlightElement, false);
      ele.addEventListener('mouseout', clearSpotlightElement, false);
    }
    else
    {
      opera.postError(ui_strings.DRAGONFLY_INFO_MESSAGE +
        "missing implementation in updateTarget in views['dom-inspector']");
      // TODO
    }
  }

  var formatProcessingInstructionValue = function(str, force_lower_case)
  {

    var r_attrs = str.split(' '), r_attr = '', i=0, attrs = '', attr = null;

    for( ; i < r_attrs.length; i++)
    {
      if(r_attr = r_attrs[i])
      {
        attr = r_attr.split('=');
        attrs += " <key>" +
          ( force_lower_case ? attr[0].toLowerCase() : attr[0] ) +
          "</key>=<value>" +
          attr[1] +
          "</value>";
      }
    }
    return attrs;
  }

  this.createView = function(container)
  {
    if( container.hasClass('tree-style') )
    {
      container.removeClass('tree-style');
    }
    var data = dom_data.getData();

    var
    tree = "
",
    i = 0,
    node = null,
    length = data.length;

    var target = dom_data.getCurrentTarget();

    var attrs = null, attr = null, k = 0, key = '';

    var is_open = 0;
    var has_only_one_child = 0;
    var one_child_text_content = '';
    var current_depth = 0;
    var child_pointer = 0;
    var child_level = 0;
    var j = 0;
    var children_length = 0;

    var closing_tags = [];

    var force_lower_case = dom_data.isTextHtml() && settings[this.id].get('force-lowercase');
    var show_comments = settings[this.id].get('show-comments');
    var show_attrs = settings[this.id].get('show-attributes');
    var node_name = '';
    var tag_head = '';
    var class_name = '';
    var re_formatted = /script|style|#comment/i;
    var scrollTop = 0;
    var container_scroll_width = 0;
    var container_first_child = null;
    var style = null;
    var is_not_script_node = true;
    var is_debug = ini.debug;

    if(!data.length)
    {
      if(!dom_data.getDataRuntimeId())
      {
        container.innerHTML =
          "

" +
            ui_strings.S_INFO_WINDOW_HAS_NO_RUNTIME +
          "

";
      }
      else
      {
        container.innerHTML = "

";
      }
      topCell.statusbar.updateInfo('');
    }
    else
    {
      for( ; node = data[i]; i += 1 )
      {
        while( current_depth > node[DEPTH] )
        {
          tree += closing_tags.pop();
          current_depth--;
        }
        current_depth = node[ DEPTH ];
        children_length = node[ CHILDREN_LENGTH ];
        child_pointer = 0;
        node_name =  ( node[NAMESPACE] ? node[NAMESPACE] + ':': '' ) +  node[NAME];
        if( force_lower_case )
        {
          node_name = node_name.toLowerCase();
        }
        switch ( node[TYPE] )
        {
          case 1:  // elements
          {
            is_not_script_node = node[NAME].toLowerCase() != 'script';
            if( show_attrs )
            {
              attrs = '';
              for( k = 0; attr = node[ATTRS][k]; k++ )
              {
                attrs += " <key>" +
                  (( attr[ATTR_PREFIX] ? attr[ATTR_PREFIX] + ':' : '' ) +
                  /* regarding escaping "<". it happens that there are very starnge keys in broken html.
                      perhaps we will have to extend the escaping to other data tokens as well */
                  ( force_lower_case ? attr[ATTR_KEY].toLowerCase() : attr[ATTR_KEY] )).replace(/</g, '<') +
                  "</key>=<value" +
                    ( /^href|src$/i.test(attr[ATTR_KEY])
                      ? " handler='dom-resource-link'"
                      : "" ) + ">\"" +
                    attr[ATTR_VALUE] +
                    "\"</value>";
              }
            }
            else
            {
              attrs = '';
            }
            child_pointer = i + 1;
            is_open = (data[child_pointer] && (node[DEPTH] < data[child_pointer][DEPTH]));
            if( is_open )
            {
              has_only_one_child = 1;
              one_child_text_content = '';
              child_level = data[child_pointer][DEPTH];
              for( ; data[child_pointer] &&  data[child_pointer][DEPTH] == child_level; child_pointer += 1 )
              {
                if (data[child_pointer][TYPE] != 3)
                {
                  has_only_one_child = 0;
                  one_child_text_content = '';
                  break;
                }
                // perhaps this needs to be adjusted. a non-closed (e.g. p) tag
                // will create an additional CRLF text node, that means the text nodes are not normalized.
                // in markup view it doesn't make sense to display such a node, still we have to ensure
                // that there is at least one text node.
                // perhaps there are other situation with not-normalized text nodes,
                // with the following code each of them will be a single text node,
                // if they contain more than just white space.
                // for exact DOM representation it is anyway better to use the DOM tree style.
                if (!one_child_text_content || !/^\s*$/.test(data[child_pointer][VALUE]))
                {
                  one_child_text_content += "<text" +
                    ( is_not_script_node ? " ref-id='" + data[child_pointer][ID] + "' " : "" ) +
                    ">" + data[child_pointer][VALUE].replace(/</g, '<') + "</text>";
                }
              }
            }

            if( is_open )
            {
              if( has_only_one_child )
              {
                class_name = re_formatted.test(node_name) ? " class='pre-wrap'" : '';
                tree += "
"+
                        "<node><" + node_name +  attrs + "></node>" +
                        one_child_text_content +
                        "<node></" + node_name + "></node>" +
                        ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                        "
";
                i = child_pointer - 1;
              }
              else
              {
                tree += "
"+
                        ( node[ CHILDREN_LENGTH ] ?
                          "<input handler='get-children' type='button' class='open'>" : '' ) +
                        "<node><" + node_name + attrs + "></node>" +
                        ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                        "
";

                closing_tags.push("
<node>" +
                                  "</" + node_name + ">" +
                                  "</node>
");
              }

            }
            else
            {
            tree += "
"+
                    ( children_length ?
                      "<input handler='get-children' type='button' class='close'>" : '' ) +
                    "<node><" + node_name + attrs + ( children_length ? '' : '/' ) + "></node>" +
                    ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                    "
";
            }
            break;
          }

          case 7:  // processing instruction
          {
            tree += "
<?" + node[NAME] + ' ' +
              formatProcessingInstructionValue(node[VALUE], force_lower_case) + "?>
";
            break;

          }

          case 8:  // comments
          {
            if( show_comments )
            {
              if( !/^\s*$/.test(node[ VALUE ] ) )
              {
                tree += "
<!--" + node[ VALUE ] + "-->
";
              }
            }
            break;

          }

          case 9:  // document node
          {
            /* makes not too much sense in the markup view
            tree += "
#document
";
            */
            break;

          }

          case 10:  // doctype
          {
            tree += "
"+
                    "<!doctype <doctype-attrs>" + node[NAME] +
                    ( node[PUBLIC_ID] ?
                      ( " PUBLIC " + "\"" + node[PUBLIC_ID] + "\"" ) :"" ) +
                    ( node[SYSTEM_ID] ?
                      ( " \"" + node[SYSTEM_ID] + "\"" ) : "" ) +
                    "</doctype-attrs>>
";
            break;
          }

          default:
          {
            if( !/^\s*$/.test(node[ VALUE ] ) )
            {
              tree +=
                "
" +
                  "<text" +
                      ( is_not_script_node ? " ref-id='"+ node[ID] + "' " : "" ) +
                      ">" + node[ VALUE ] + "</text>" +
                "
";
            }
          }

        }
      }

      while( closing_tags.length )
      {
        tree += closing_tags.pop();
      }
      tree += "
";
      scrollTop = container.scrollTop;
      container.innerHTML = tree;
      container.scrollTop = scrollTop;
      container_scroll_width = container.scrollWidth;
      container_first_child = container.firstChild;
      // preformatted text is in a span
      // that does just add to the scroll width but does not expand the container
      if( container_scroll_width > container_first_child.offsetWidth )
      {
        if( !div_padding_value )
        {
          style = getComputedStyle(container_first_child, null);
          div_padding_value = (
            parseInt( style.getPropertyValue('padding-left') ) +
            parseInt( style.getPropertyValue('padding-right') ) );
        }
        container.firstChild.style.width = ( container_scroll_width - div_padding_value ) + 'px';
        setTimeout(function(){container.scrollLeft = 0;}, 0);
      }
      this.updateTarget();
      topCell.statusbar.updateInfo(templates.breadcrumb(dom_data.getCSSPath()).
          concat(['onmouseover', helpers.breadcrumbSpotlight,
                  'onmouseout', helpers.breadcrumbClearSpotlight]));
    }
  }

}

<commit_msg>fixed an issue with non escaped '<' charakeres in DOM comments<commit_after>/**
  * @constructor
  * @extends ViewBase
  * @see DOM_tree_style this class can be dynamically exchanged with DOM_tree_style
  */

var DOM_markup_style = function(id, name, container_class)
{
  var self = this;

  const
  ID = 0,
  TYPE = 1,
  NAME = 2,
  DEPTH = 3,
  NAMESPACE = 4,
  VALUE = 7,
  ATTRS = 5,
  ATTR_PREFIX = 0,
  ATTR_KEY = 1,
  ATTR_VALUE = 2,
  CHILDREN_LENGTH = 6,
  PUBLIC_ID = 8,
  SYSTEM_ID = 9,
  INDENT = "  ",
  LINEBREAK = '\n';

  var getIndent = function(count)
  {
    var ret = '';
    if(count)
    {
      count--;
    }
    while(count)
    {
      ret += INDENT;
      count--;
    }
    return ret;
  };

  var div_padding_value = 0;

  var spotlightElement = function()
  {
    hostspotlighter.spotlight(parseInt(this.getAttribute('ref-id')));
  }

  var clearSpotlightElement = function()
  {
    hostspotlighter.clearSpotlight();
  }

  this.updateTarget = function(ele, obj_id)
  {
    if(ele)
    {
      var target = document.getElementById('target-element');
      if(target)
      {
        target.removeAttribute('id');
        target.removeEventListener('mouseover', spotlightElement, false);
        target.removeEventListener('mouseout', clearSpotlightElement, false);
      }
      if(/<\//.test(ele.firstChild.nodeValue))
      {
        while( ( ele = ele.previousSibling ) && ele.getAttribute('ref-id') != obj_id );
      }
      topCell.statusbar.updateInfo
      (
        // the same template is used with inner html
        templates.breadcrumb(dom_data.getCSSPath()).
          concat(['onmouseover', helpers.breadcrumbSpotlight,
                  'onmouseout', helpers.breadcrumbClearSpotlight])
      );
    }
    if(ele || ( ele = document.getElementById('target-element') ) )
    {
      ele.id = 'target-element';
      ele.addEventListener('mouseover', spotlightElement, false);
      ele.addEventListener('mouseout', clearSpotlightElement, false);
    }
    else
    {
      opera.postError(ui_strings.DRAGONFLY_INFO_MESSAGE +
        "missing implementation in updateTarget in views['dom-inspector']");
      // TODO
    }
  }

  var formatProcessingInstructionValue = function(str, force_lower_case)
  {

    var r_attrs = str.split(' '), r_attr = '', i=0, attrs = '', attr = null;

    for( ; i < r_attrs.length; i++)
    {
      if(r_attr = r_attrs[i])
      {
        attr = r_attr.split('=');
        attrs += " <key>" +
          ( force_lower_case ? attr[0].toLowerCase() : attr[0] ) +
          "</key>=<value>" +
          attr[1] +
          "</value>";
      }
    }
    return attrs;
  }

  this.createView = function(container)
  {
    if( container.hasClass('tree-style') )
    {
      container.removeClass('tree-style');
    }
    var data = dom_data.getData();

    var
    tree = "
",
    i = 0,
    node = null,
    length = data.length;

    var target = dom_data.getCurrentTarget();

    var attrs = null, attr = null, k = 0, key = '';

    var is_open = 0;
    var has_only_one_child = 0;
    var one_child_text_content = '';
    var current_depth = 0;
    var child_pointer = 0;
    var child_level = 0;
    var j = 0;
    var children_length = 0;

    var closing_tags = [];

    var force_lower_case = dom_data.isTextHtml() && settings[this.id].get('force-lowercase');
    var show_comments = settings[this.id].get('show-comments');
    var show_attrs = settings[this.id].get('show-attributes');
    var node_name = '';
    var tag_head = '';
    var class_name = '';
    var re_formatted = /script|style|#comment/i;
    var scrollTop = 0;
    var container_scroll_width = 0;
    var container_first_child = null;
    var style = null;
    var is_not_script_node = true;
    var is_debug = ini.debug;

    if(!data.length)
    {
      if(!dom_data.getDataRuntimeId())
      {
        container.innerHTML =
          "

" +
            ui_strings.S_INFO_WINDOW_HAS_NO_RUNTIME +
          "

";
      }
      else
      {
        container.innerHTML = "

";
      }
      topCell.statusbar.updateInfo('');
    }
    else
    {
      for( ; node = data[i]; i += 1 )
      {
        while( current_depth > node[DEPTH] )
        {
          tree += closing_tags.pop();
          current_depth--;
        }
        current_depth = node[ DEPTH ];
        children_length = node[ CHILDREN_LENGTH ];
        child_pointer = 0;
        node_name =  ( node[NAMESPACE] ? node[NAMESPACE] + ':': '' ) +  node[NAME];
        if( force_lower_case )
        {
          node_name = node_name.toLowerCase();
        }
        switch ( node[TYPE] )
        {
          case 1:  // elements
          {
            is_not_script_node = node[NAME].toLowerCase() != 'script';
            if( show_attrs )
            {
              attrs = '';
              for( k = 0; attr = node[ATTRS][k]; k++ )
              {
                attrs += " <key>" +
                  (( attr[ATTR_PREFIX] ? attr[ATTR_PREFIX] + ':' : '' ) +
                  /* regarding escaping "<". it happens that there are very starnge keys in broken html.
                      perhaps we will have to extend the escaping to other data tokens as well */
                  ( force_lower_case ? attr[ATTR_KEY].toLowerCase() : attr[ATTR_KEY] )).replace(/</g, '<') +
                  "</key>=<value" +
                    ( /^href|src$/i.test(attr[ATTR_KEY])
                      ? " handler='dom-resource-link'"
                      : "" ) + ">\"" +
                    attr[ATTR_VALUE] +
                    "\"</value>";
              }
            }
            else
            {
              attrs = '';
            }
            child_pointer = i + 1;
            is_open = (data[child_pointer] && (node[DEPTH] < data[child_pointer][DEPTH]));
            if( is_open )
            {
              has_only_one_child = 1;
              one_child_text_content = '';
              child_level = data[child_pointer][DEPTH];
              for( ; data[child_pointer] &&  data[child_pointer][DEPTH] == child_level; child_pointer += 1 )
              {
                if (data[child_pointer][TYPE] != 3)
                {
                  has_only_one_child = 0;
                  one_child_text_content = '';
                  break;
                }
                // perhaps this needs to be adjusted. a non-closed (e.g. p) tag
                // will create an additional CRLF text node, that means the text nodes are not normalized.
                // in markup view it doesn't make sense to display such a node, still we have to ensure
                // that there is at least one text node.
                // perhaps there are other situation with not-normalized text nodes,
                // with the following code each of them will be a single text node,
                // if they contain more than just white space.
                // for exact DOM representation it is anyway better to use the DOM tree style.
                if (!one_child_text_content || !/^\s*$/.test(data[child_pointer][VALUE]))
                {
                  one_child_text_content += "<text" +
                    ( is_not_script_node ? " ref-id='" + data[child_pointer][ID] + "' " : "" ) +
                    ">" + data[child_pointer][VALUE].replace(/</g, '<') + "</text>";
                }
              }
            }

            if( is_open )
            {
              if( has_only_one_child )
              {
                class_name = re_formatted.test(node_name) ? " class='pre-wrap'" : '';
                tree += "
"+
                        "<node><" + node_name +  attrs + "></node>" +
                        one_child_text_content +
                        "<node></" + node_name + "></node>" +
                        ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                        "
";
                i = child_pointer - 1;
              }
              else
              {
                tree += "
"+
                        ( node[ CHILDREN_LENGTH ] ?
                          "<input handler='get-children' type='button' class='open'>" : '' ) +
                        "<node><" + node_name + attrs + "></node>" +
                        ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                        "
";

                closing_tags.push("
<node>" +
                                  "</" + node_name + ">" +
                                  "</node>
");
              }

            }
            else
            {
            tree += "
"+
                    ( children_length ?
                      "<input handler='get-children' type='button' class='close'>" : '' ) +
                    "<node><" + node_name + attrs + ( children_length ? '' : '/' ) + "></node>" +
                    ( is_debug && ( " <d>[" + node[ ID ] +  "]</d>" ) || "" ) +
                    "
";
            }
            break;
          }

          case 7:  // processing instruction
          {
            tree += "
<?" + node[NAME] + ' ' +
              formatProcessingInstructionValue(node[VALUE], force_lower_case) + "?>
";
            break;

          }

          case 8:  // comments
          {
            if( show_comments )
            {
              if( !/^\s*$/.test(node[ VALUE ] ) )
              {
                tree += "
<!--" + node[VALUE].replace(/</g, '<') + "-->
";
              }
            }
            break;

          }

          case 9:  // document node
          {
            /* makes not too much sense in the markup view
            tree += "
#document
";
            */
            break;

          }

          case 10:  // doctype
          {
            tree += "
"+
                    "<!doctype <doctype-attrs>" + node[NAME] +
                    ( node[PUBLIC_ID] ?
                      ( " PUBLIC " + "\"" + node[PUBLIC_ID] + "\"" ) :"" ) +
                    ( node[SYSTEM_ID] ?
                      ( " \"" + node[SYSTEM_ID] + "\"" ) : "" ) +
                    "</doctype-attrs>>
";
            break;
          }

          default:
          {
            if( !/^\s*$/.test(node[ VALUE ] ) )
            {
              tree +=
                "
" +
                  "<text" +
                      ( is_not_script_node ? " ref-id='"+ node[ID] + "' " : "" ) +
                      ">" + node[ VALUE ] + "</text>" +
                "
";
            }
          }

        }
      }

      while( closing_tags.length )
      {
        tree += closing_tags.pop();
      }
      tree += "
";
      scrollTop = container.scrollTop;
      container.innerHTML = tree;
      container.scrollTop = scrollTop;
      container_scroll_width = container.scrollWidth;
      container_first_child = container.firstChild;
      // preformatted text is in a span
      // that does just add to the scroll width but does not expand the container
      if( container_scroll_width > container_first_child.offsetWidth )
      {
        if( !div_padding_value )
        {
          style = getComputedStyle(container_first_child, null);
          div_padding_value = (
            parseInt( style.getPropertyValue('padding-left') ) +
            parseInt( style.getPropertyValue('padding-right') ) );
        }
        container.firstChild.style.width = ( container_scroll_width - div_padding_value ) + 'px';
        setTimeout(function(){container.scrollLeft = 0;}, 0);
      }
      this.updateTarget();
      topCell.statusbar.updateInfo(templates.breadcrumb(dom_data.getCSSPath()).
          concat(['onmouseover', helpers.breadcrumbSpotlight,
                  'onmouseout', helpers.breadcrumbClearSpotlight]));
    }
  }

}

<|endoftext|>


<commit_before>define([
	'goo/math/Matrix4x4',
	'goo/math/Vector4'
], /** @lends SplineInterpolator */ function (
	Matrix4x4,
	Vector4
) {
	'use strict';

	var clamp = function (x, lower, upper) {
		return Math.min(Math.max(x, lower), upper);
	};

	/**
	 * @class Interpolates an attribute of an entity.
	 * @constructor
	 * @description Creates a new SplineInterpolator.
	 * @param {Object} [properties] Object containing spline properties.
	 */

	function SplineInterpolator (properties) {
		properties = properties || {};

		this.controlPoint = 0;
		this.controlPoints = properties.controlPoints || [];
		this.elapsedTime = 0.0;
		this.enabled = properties.enabled || true;
		this.firstIteration = true;
		this.tolerance = properties.tolerance || 0.01;
		this.beforeFunction = properties.beforeFunction || function (entity) {
			return entity.transformComponent.transform.translation.data;
		};
		this.updateFunction = properties.updateFunction || function (entity, array) {
			entity.transformComponent.transform.translation.set(array);
			entity.transformComponent.setUpdated();
		};
		this.afterFunction = properties.afterFunction || function () {};
	}

	SplineInterpolator.CATMULL_ROM = new Matrix4x4(-0.5, 1.0, -0.5, 0.0, 1.5, -2.5, 0.0, 1.0, -1.5, 2.0, 0.5, 0.0, 0.5, -0.5, 0.0, 0.0);
	SplineInterpolator.UNIFORM_CUBIC = new Matrix4x4(-0.16667, 0.5, -0.5, 0.16667, 0.5, -1.0, 0.0, 0.66667, -0.5, 0.5, 0.5, 0.16667, 0.16667, 0.0, 0.0, 0.0);

	/**
	 * @description Performs one iteration of the script.
	 * @param {Entity} entity The entity controlled by the script.
	 * @param {Float} tpf The time that has elapsed between two consequent runs.
	 */

	SplineInterpolator.prototype.run = function (entity, tpf) {
		if (this.firstIteration) {
			this.firstIteration = false;

			try {
				this.controlPoints.unshift({ 'time' : 0.0, 'value' : this.beforeFunction(entity) });
			} catch (e) {
				this.enabled = false;

				return;
			}
		}

		var ia = clamp(this.controlPoint - 1, 0, this.controlPoints.length - 1);
		var ib = clamp(this.controlPoint + 0, 0, this.controlPoints.length - 1);
		var ic = clamp(this.controlPoint + 1, 0, this.controlPoints.length - 1);
		var id = clamp(this.controlPoint + 2, 0, this.controlPoints.length - 1);

		var factor = (this.controlPoints[ic].time > this.controlPoints[ib].time) ? (this.elapsedTime - this.controlPoints[ib].time) / (this.controlPoints[ic].time - this.controlPoints[ib].time) : 0.0;
		var t = SplineInterpolator.CATMULL_ROM.applyPre(new Vector4(factor * factor * factor, factor * factor, factor, 1.0));
		var array = new Array(this.controlPoints[0].value.length);
		var difference = 0.0;

		for (var i = 0; i < array.length; i++) {
			array[i] = 0.0;
			array[i] += this.controlPoints[ia].value[i] * t[0];
			array[i] += this.controlPoints[ib].value[i] * t[1];
			array[i] += this.controlPoints[ic].value[i] * t[2];
			array[i] += this.controlPoints[id].value[i] * t[3];

			difference += Math.abs(this.controlPoints[this.controlPoints.length - 1].value[i] - array[i]);
		}

		try {
			this.updateFunction(entity, array);
		} catch (e) {
			this.enabled = false;

			return;
		}

		this.elapsedTime += tpf;

		if (this.elapsedTime >= this.controlPoints[ic].time) {
			this.controlPoint++;
		}

		if (this.controlPoint >= this.controlPoints.length - 1 || difference < this.tolerance) {
			try {
				this.afterFunction(entity);
			} catch(e) {}

			this.enabled = false;

			return;
		}
	};

	return SplineInterpolator;
});
<commit_msg>Fixed a bug where the current translation always was the first control point.<commit_after>define([
	'goo/math/Matrix4x4',
	'goo/math/Vector4'
], /** @lends SplineInterpolator */ function (
	Matrix4x4,
	Vector4
) {
	'use strict';

	var clamp = function (x, lower, upper) {
		return Math.min(Math.max(x, lower), upper);
	};

	/**
	 * @class Interpolates an attribute of an entity.
	 * @constructor
	 * @description Creates a new SplineInterpolator.
	 * @param {Object} [properties] Object containing spline properties.
	 */

	function SplineInterpolator (properties) {
		properties = properties || {};

		this.controlPoint = 0;
		this.controlPoints = properties.controlPoints || [];
		this.elapsedTime = 0.0;
		this.enabled = properties.enabled || true;
		this.firstIteration = true;
		this.tolerance = properties.tolerance || 0.01;
		this.beforeFunction = properties.beforeFunction || function (entity) {
			return entity.transformComponent.transform.translation.clone().data;
		};
		this.updateFunction = properties.updateFunction || function (entity, array) {
			entity.transformComponent.transform.translation.set(array);
			entity.transformComponent.setUpdated();
		};
		this.afterFunction = properties.afterFunction || function () {};
	}

	SplineInterpolator.CATMULL_ROM = new Matrix4x4(-0.5, 1.0, -0.5, 0.0, 1.5, -2.5, 0.0, 1.0, -1.5, 2.0, 0.5, 0.0, 0.5, -0.5, 0.0, 0.0);
	SplineInterpolator.UNIFORM_CUBIC = new Matrix4x4(-0.16667, 0.5, -0.5, 0.16667, 0.5, -1.0, 0.0, 0.66667, -0.5, 0.5, 0.5, 0.16667, 0.16667, 0.0, 0.0, 0.0);

	/**
	 * @description Performs one iteration of the script.
	 * @param {Entity} entity The entity controlled by the script.
	 * @param {Float} tpf The time that has elapsed between two consequent runs.
	 */

	SplineInterpolator.prototype.run = function (entity, tpf) {
		if (this.firstIteration) {
			this.firstIteration = false;

			try {
				this.controlPoints.unshift({ 'time' : 0.0, 'value' : this.beforeFunction(entity) });
			} catch (e) {
				this.enabled = false;

				return;
			}
		}

		var ia = clamp(this.controlPoint - 1, 0, this.controlPoints.length - 1);
		var ib = clamp(this.controlPoint + 0, 0, this.controlPoints.length - 1);
		var ic = clamp(this.controlPoint + 1, 0, this.controlPoints.length - 1);
		var id = clamp(this.controlPoint + 2, 0, this.controlPoints.length - 1);

		var factor = (this.controlPoints[ic].time > this.controlPoints[ib].time) ? (this.elapsedTime - this.controlPoints[ib].time) / (this.controlPoints[ic].time - this.controlPoints[ib].time) : 0.0;
		var t = SplineInterpolator.CATMULL_ROM.applyPre(new Vector4(factor * factor * factor, factor * factor, factor, 1.0));
		var array = new Array(this.controlPoints[0].value.length);
		var difference = 0.0;

		for (var i = 0; i < array.length; i++) {
			array[i] = 0.0;
			array[i] += this.controlPoints[ia].value[i] * t[0];
			array[i] += this.controlPoints[ib].value[i] * t[1];
			array[i] += this.controlPoints[ic].value[i] * t[2];
			array[i] += this.controlPoints[id].value[i] * t[3];

			difference += Math.abs(this.controlPoints[this.controlPoints.length - 1].value[i] - array[i]);
		}

		try {
			this.updateFunction(entity, array);
		} catch (e) {
			this.enabled = false;

			return;
		}

		this.elapsedTime += tpf;

		if (this.elapsedTime >= this.controlPoints[ic].time) {
			this.controlPoint++;
		}

		if (this.controlPoint >= this.controlPoints.length - 1 || difference < this.tolerance) {
			try {
				this.afterFunction(entity);
			} catch(e) {}

			this.enabled = false;

			return;
		}
	};

	return SplineInterpolator;
});
<|endoftext|>


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

/* @flow */
import React, { cloneElement } from 'react';
import { ellipsis } from 'polished';
import { createStyledComponent, pxToEm, getNormalizedValue } from '../styles';

type Props = {
  /** Rendered content of the component */
  children?: React$Node,
  /** Displays a circular Button */
  circular?: boolean,
  /** Disables the Button */
  disabled?: boolean,
  /** Element to be used as the root node - e.g. `a` can be used to create a link that is styled like a Button */
  element?: $FlowFixMe, // Should allow string | React class
  /** Stretch Button to fill its container */
  fullWidth?: boolean,
  /** Icon that goes after the children*/
  iconEnd?: React$Element<*>,
  /** Icon that goes before the children */
  iconStart?: React$Element<*>,
  /** Display a minimal Button */
  minimal?: boolean,
  /** Called with the click event */
  onClick?: (event: SyntheticEvent<>) => void,
  /** Display a primary Button */
  primary?: boolean,
  /** Available sizes */
  size?: 'small' | 'medium' | 'large' | 'jumbo',
  /** Available types */
  type?: string,
  /** Available variants */
  variant?: 'regular' | 'danger' | 'success' | 'warning'
};

export const componentTheme = (baseTheme: Object) => ({
  Button_backgroundColor: baseTheme.color_gray_20,
  Button_backgroundColor_active: baseTheme.color_gray_30,
  Button_backgroundColor_focus: baseTheme.color_gray_20,
  Button_backgroundColor_hover: baseTheme.color_gray_10,
  Button_backgroundColor_minimal_active: baseTheme.color_gray_20,
  Button_backgroundColor_minimal_hover: baseTheme.color_gray_10,
  Button_backgroundColor_primary: baseTheme.color_theme_60,
  Button_backgroundColor_primary_active: baseTheme.color_theme_70,
  Button_backgroundColor_primary_focus: baseTheme.color_theme_60,
  Button_backgroundColor_primary_hover: baseTheme.color_theme_50,
  Button_borderColor: baseTheme.borderColor,
  Button_borderColor_focus: baseTheme.color_white,
  Button_borderRadius: baseTheme.borderRadius_1,
  Button_borderWidth: 1, // px
  Button_boxShadow_focus: `0 0 0 1px ${baseTheme.borderColor_focus}`,
  Button_color_text: baseTheme.color_gray_100,
  Button_color_text_minimal: baseTheme.color_text_primary,
  Button_color_text_primary: baseTheme.color_text_onprimary,
  Button_fontWeight: baseTheme.fontWeight_semiBold,
  Button_paddingHorizontal: baseTheme.space_inset_sm,
  Button_paddingIconOnly_small: pxToEm(3),
  Button_paddingIconOnly_medium: pxToEm(7),
  Button_paddingIconOnly_large: pxToEm(7),
  Button_paddingIconOnly_jumbo: pxToEm(13),
  Button_height_small: baseTheme.size_small,
  Button_height_medium: baseTheme.size_medium,
  Button_height_large: baseTheme.size_large,
  Button_height_jumbo: baseTheme.size_jumbo,

  ButtonContent_fontSize: baseTheme.fontSize_ui,
  ButtonContent_fontSize_small: pxToEm(12),

  ButtonIcon_margin: baseTheme.space_inset_sm,

  ...baseTheme
});

function chooseColor({ disabled, primary, minimal }: Props, theme) {
  if (disabled) {
    return theme.color_text_disabled;
  } else if (primary) {
    return theme.Button_color_text_primary;
  } else if (minimal) {
    return theme.Button_color_text_minimal;
  } else {
    return theme.Button_color_text;
  }
}

const styles = {
  button: props => {
    let theme = componentTheme(props.theme);
    const {
      circular,
      disabled,
      fullWidth,
      minimal,
      primary,
      size,
      text,
      variant
    } = props;

    if (variant !== 'regular') {
      // prettier-ignore
      theme = {
        ...theme,
        Button_backgroundColor_primary: theme[`backgroundColor_${variant}`],
        Button_backgroundColor_primary_active: theme[`backgroundColor_${variant}_active`],
        Button_backgroundColor_primary_focus: theme[`backgroundColor_${variant}_focus`],
        Button_backgroundColor_primary_hover: theme[`backgroundColor_${variant}_hover`],
        Button_boxShadow_focus: `0 0 0 1px ${theme[`borderColor_${variant}_focus`]}`,
        Button_color_text: theme[`color_text_${variant}`],
        Button_color_text_minimal: theme[`color_text_${variant}`],
        Button_color_text_primary: theme[`color_text_on${variant}`]
      };
    }

    const color = chooseColor(props, theme);
    return {
      backgroundColor: (() => {
        if (disabled && !minimal) {
          return theme.color_gray_30;
        } else if (primary) {
          return theme.Button_backgroundColor_primary;
        } else if (minimal) {
          return 'transparent';
        } else {
          return theme.Button_backgroundColor;
        }
      })(),
      borderColor:
        disabled || primary || minimal
          ? 'transparent'
          : theme.Button_borderColor,
      borderRadius: circular
        ? `${parseFloat(theme[`Button_height_${size}`]) / 2}em`
        : theme.Button_borderRadius,
      borderStyle: 'solid',
      borderWidth: `${theme.Button_borderWidth}px`,
      color,
      cursor: disabled ? 'default' : 'pointer',
      display: 'inline-block',
      fontWeight: theme.Button_fontWeight,
      height: theme[`Button_height_${size}`],
      // if the user puts in a small icon in a large button
      // we want to force the button to be round/square
      // (really just pertinent on icon-only buttons)
      minWidth: theme[`Button_height_${size}`],
      padding:
        text === undefined
          ? theme[`Button_paddingIconOnly_${size}`]
          : `0 ${theme.Button_paddingHorizontal}`,
      textDecoration: 'none',
      verticalAlign: 'middle',
      width: fullWidth && '100%',
      '&:focus': {
        backgroundColor: (() => {
          if (primary) {
            return theme.Button_backgroundColor_primary_focus;
          } else if (minimal) {
            return theme.Button_backgroundColor_minimal_focus;
          } else {
            return theme.Button_backgroundColor_focus;
          }
        })(),
        borderColor: theme.Button_borderColor_focus,
        boxShadow: theme.Button_boxShadow_focus,
        color,
        textDecoration: 'none'
      },
      '&:hover': {
        backgroundColor: (() => {
          if (!disabled) {
            if (primary) {
              return theme.Button_backgroundColor_primary_hover;
            } else if (minimal) {
              return theme.Button_backgroundColor_minimal_hover;
            } else {
              return theme.Button_backgroundColor_hover;
            }
          }
        })(),
        color,
        textDecoration: 'none'
      },
      // `:active` must be last, to follow LVHFA order:
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:active
      '&:active': {
        backgroundColor: (() => {
          if (!disabled) {
            if (primary) {
              return theme.Button_backgroundColor_primary_active;
            } else if (minimal) {
              return theme.Button_backgroundColor_minimal_active;
            } else {
              return theme.Button_backgroundColor_active;
            }
          }
        })(),
        color
      },
      '&::-moz-focus-inner': { border: 0 },

      '& [role="icon"]': {
        boxSizing: 'content-box',
        fill:
          disabled || primary || minimal || variant !== 'regular'
            ? 'currentColor'
            : theme.Button_backgroundColor_primary,
        display: 'block',

        '&:first-child': {
          marginLeft:
            theme.direction === 'rtl' ? theme.ButtonIcon_margin : null,
          marginRight:
            theme.direction === 'ltr' ? theme.ButtonIcon_margin : null
        },

        '&:last-child': {
          marginLeft:
            theme.direction === 'ltr' ? theme.ButtonIcon_margin : null,
          marginRight:
            theme.direction === 'rtl' ? theme.ButtonIcon_margin : null
        },

        '&:only-child': {
          margin: 0
        }
      }
    };
  },
  content: props => {
    const theme = componentTheme(props.theme);
    const { size } = props;

    let paddings;

    const fontSize =
      size === 'small'
        ? theme.ButtonContent_fontSize_small
        : theme.ButtonContent_fontSize;

    if (size === undefined || size === 'large' || size === 'jumbo') {
      const padding = getNormalizedValue(
        theme.Button_paddingHorizontal,
        fontSize
      );
      paddings = {
        '&:first-child': {
          paddingLeft: theme.direction === 'ltr' ? padding : null,
          paddingRight: theme.direction === 'rtl' ? padding : null
        },

        '&:last-child': {
          paddingLeft: theme.direction === 'rtl' ? padding : null,
          paddingRight: theme.direction === 'ltr' ? padding : null
        }
      };
    }

    return {
      ...ellipsis('100%'),

      display: 'block',
      fontSize,
      lineHeight: getNormalizedValue(theme[`Button_height_${size}`], fontSize),
      ...paddings
    };
  },
  inner: {
    alignItems: 'center',
    display: 'inline-flex',
    justifyContent: 'center',
    maxHeight: '100%',
    width: '100%'
  }
};

const Content = createStyledComponent('span', styles.content);
const Inner = createStyledComponent('span', styles.inner);

function isTypeButton(type: ?string) {
  const buttonTypes = ['button', 'submit', 'reset'];
  return buttonTypes.indexOf(type) !== -1;
}

function filterProps({ element, type }: Props) {
  // When element is a component, e.g. ReactRouterLink,
  // these are not filtered automatically by rootEl
  const invalidComponentProps = ['primary', 'text', 'variant'];
  const invalidLinkProps =
    element === 'a' && isTypeButton(type) ? ['type'] : [];
  return Array.prototype.concat(invalidComponentProps, invalidLinkProps);
}

/**
 * The Button component represents a clickable button.
 * Buttons draw attention to actions that can be performed in your app.
 * Buttons are used to trigger any sort of event.
 *
 * Always use the appropriate variant for your button, and write a clear, concise label to effectively communicate intention.
 */
export default function Button({
  children,
  element = 'button',
  iconStart,
  iconEnd,
  size = 'large',
  type = 'button',
  variant = 'regular',
  ...restProps
}: Props) {
  const rootProps = {
    size,
    text: children,
    type,
    variant,
    ...restProps
  };

  const Root = createStyledComponent(element, styles.button, {
    filterProps: filterProps(rootProps),
    includeStyleReset: true,
    rootEl: element
  });

  const iconSize = {
    small: 'medium',
    medium: 'medium',
    large: pxToEm(24),
    jumbo: pxToEm(24)
  };
  const startIcon = iconStart
    ? cloneElement(iconStart, { size: iconSize[size] })
    : null;
  const endIcon = iconEnd
    ? cloneElement(iconEnd, { size: iconSize[size] })
    : null;

  return (
    <Root {...rootProps}>
      <Inner>
        {startIcon}
        {children && <Content size={size}>{children}</Content>}
        {endIcon}
      </Inner>
    </Root>
  );
}
<commit_msg>chore(button): Fix type prop filtering<commit_after>/**
 * Copyright 2017 CA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* @flow */
import React, { cloneElement } from 'react';
import { ellipsis } from 'polished';
import { createStyledComponent, pxToEm, getNormalizedValue } from '../styles';

type Props = {
  /** Rendered content of the component */
  children?: React$Node,
  /** Displays a circular Button */
  circular?: boolean,
  /** Disables the Button */
  disabled?: boolean,
  /** Element to be used as the root node - e.g. `a` can be used to create a link that is styled like a Button */
  element?: $FlowFixMe, // Should allow string | React class
  /** Stretch Button to fill its container */
  fullWidth?: boolean,
  /** Icon that goes after the children*/
  iconEnd?: React$Element<*>,
  /** Icon that goes before the children */
  iconStart?: React$Element<*>,
  /** Display a minimal Button */
  minimal?: boolean,
  /** Called with the click event */
  onClick?: (event: SyntheticEvent<>) => void,
  /** Display a primary Button */
  primary?: boolean,
  /** Available sizes */
  size?: 'small' | 'medium' | 'large' | 'jumbo',
  /** Available types */
  type?: string,
  /** Available variants */
  variant?: 'regular' | 'danger' | 'success' | 'warning'
};

export const componentTheme = (baseTheme: Object) => ({
  Button_backgroundColor: baseTheme.color_gray_20,
  Button_backgroundColor_active: baseTheme.color_gray_30,
  Button_backgroundColor_focus: baseTheme.color_gray_20,
  Button_backgroundColor_hover: baseTheme.color_gray_10,
  Button_backgroundColor_minimal_active: baseTheme.color_gray_20,
  Button_backgroundColor_minimal_hover: baseTheme.color_gray_10,
  Button_backgroundColor_primary: baseTheme.color_theme_60,
  Button_backgroundColor_primary_active: baseTheme.color_theme_70,
  Button_backgroundColor_primary_focus: baseTheme.color_theme_60,
  Button_backgroundColor_primary_hover: baseTheme.color_theme_50,
  Button_borderColor: baseTheme.borderColor,
  Button_borderColor_focus: baseTheme.color_white,
  Button_borderRadius: baseTheme.borderRadius_1,
  Button_borderWidth: 1, // px
  Button_boxShadow_focus: `0 0 0 1px ${baseTheme.borderColor_focus}`,
  Button_color_text: baseTheme.color_gray_100,
  Button_color_text_minimal: baseTheme.color_text_primary,
  Button_color_text_primary: baseTheme.color_text_onprimary,
  Button_fontWeight: baseTheme.fontWeight_semiBold,
  Button_paddingHorizontal: baseTheme.space_inset_sm,
  Button_paddingIconOnly_small: pxToEm(3),
  Button_paddingIconOnly_medium: pxToEm(7),
  Button_paddingIconOnly_large: pxToEm(7),
  Button_paddingIconOnly_jumbo: pxToEm(13),
  Button_height_small: baseTheme.size_small,
  Button_height_medium: baseTheme.size_medium,
  Button_height_large: baseTheme.size_large,
  Button_height_jumbo: baseTheme.size_jumbo,

  ButtonContent_fontSize: baseTheme.fontSize_ui,
  ButtonContent_fontSize_small: pxToEm(12),

  ButtonIcon_margin: baseTheme.space_inset_sm,

  ...baseTheme
});

function chooseColor({ disabled, primary, minimal }: Props, theme) {
  if (disabled) {
    return theme.color_text_disabled;
  } else if (primary) {
    return theme.Button_color_text_primary;
  } else if (minimal) {
    return theme.Button_color_text_minimal;
  } else {
    return theme.Button_color_text;
  }
}

const styles = {
  button: props => {
    let theme = componentTheme(props.theme);
    const {
      circular,
      disabled,
      fullWidth,
      minimal,
      primary,
      size,
      text,
      variant
    } = props;

    if (variant !== 'regular') {
      // prettier-ignore
      theme = {
        ...theme,
        Button_backgroundColor_primary: theme[`backgroundColor_${variant}`],
        Button_backgroundColor_primary_active: theme[`backgroundColor_${variant}_active`],
        Button_backgroundColor_primary_focus: theme[`backgroundColor_${variant}_focus`],
        Button_backgroundColor_primary_hover: theme[`backgroundColor_${variant}_hover`],
        Button_boxShadow_focus: `0 0 0 1px ${theme[`borderColor_${variant}_focus`]}`,
        Button_color_text: theme[`color_text_${variant}`],
        Button_color_text_minimal: theme[`color_text_${variant}`],
        Button_color_text_primary: theme[`color_text_on${variant}`]
      };
    }

    const color = chooseColor(props, theme);
    return {
      backgroundColor: (() => {
        if (disabled && !minimal) {
          return theme.color_gray_30;
        } else if (primary) {
          return theme.Button_backgroundColor_primary;
        } else if (minimal) {
          return 'transparent';
        } else {
          return theme.Button_backgroundColor;
        }
      })(),
      borderColor:
        disabled || primary || minimal
          ? 'transparent'
          : theme.Button_borderColor,
      borderRadius: circular
        ? `${parseFloat(theme[`Button_height_${size}`]) / 2}em`
        : theme.Button_borderRadius,
      borderStyle: 'solid',
      borderWidth: `${theme.Button_borderWidth}px`,
      color,
      cursor: disabled ? 'default' : 'pointer',
      display: 'inline-block',
      fontWeight: theme.Button_fontWeight,
      height: theme[`Button_height_${size}`],
      // if the user puts in a small icon in a large button
      // we want to force the button to be round/square
      // (really just pertinent on icon-only buttons)
      minWidth: theme[`Button_height_${size}`],
      padding:
        text === undefined
          ? theme[`Button_paddingIconOnly_${size}`]
          : `0 ${theme.Button_paddingHorizontal}`,
      textDecoration: 'none',
      verticalAlign: 'middle',
      width: fullWidth && '100%',
      '&:focus': {
        backgroundColor: (() => {
          if (primary) {
            return theme.Button_backgroundColor_primary_focus;
          } else if (minimal) {
            return theme.Button_backgroundColor_minimal_focus;
          } else {
            return theme.Button_backgroundColor_focus;
          }
        })(),
        borderColor: theme.Button_borderColor_focus,
        boxShadow: theme.Button_boxShadow_focus,
        color,
        textDecoration: 'none'
      },
      '&:hover': {
        backgroundColor: (() => {
          if (!disabled) {
            if (primary) {
              return theme.Button_backgroundColor_primary_hover;
            } else if (minimal) {
              return theme.Button_backgroundColor_minimal_hover;
            } else {
              return theme.Button_backgroundColor_hover;
            }
          }
        })(),
        color,
        textDecoration: 'none'
      },
      // `:active` must be last, to follow LVHFA order:
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:active
      '&:active': {
        backgroundColor: (() => {
          if (!disabled) {
            if (primary) {
              return theme.Button_backgroundColor_primary_active;
            } else if (minimal) {
              return theme.Button_backgroundColor_minimal_active;
            } else {
              return theme.Button_backgroundColor_active;
            }
          }
        })(),
        color
      },
      '&::-moz-focus-inner': { border: 0 },

      '& [role="icon"]': {
        boxSizing: 'content-box',
        fill:
          disabled || primary || minimal || variant !== 'regular'
            ? 'currentColor'
            : theme.Button_backgroundColor_primary,
        display: 'block',

        '&:first-child': {
          marginLeft:
            theme.direction === 'rtl' ? theme.ButtonIcon_margin : null,
          marginRight:
            theme.direction === 'ltr' ? theme.ButtonIcon_margin : null
        },

        '&:last-child': {
          marginLeft:
            theme.direction === 'ltr' ? theme.ButtonIcon_margin : null,
          marginRight:
            theme.direction === 'rtl' ? theme.ButtonIcon_margin : null
        },

        '&:only-child': {
          margin: 0
        }
      }
    };
  },
  content: props => {
    const theme = componentTheme(props.theme);
    const { size } = props;

    let paddings;

    const fontSize =
      size === 'small'
        ? theme.ButtonContent_fontSize_small
        : theme.ButtonContent_fontSize;

    if (size === undefined || size === 'large' || size === 'jumbo') {
      const padding = getNormalizedValue(
        theme.Button_paddingHorizontal,
        fontSize
      );
      paddings = {
        '&:first-child': {
          paddingLeft: theme.direction === 'ltr' ? padding : null,
          paddingRight: theme.direction === 'rtl' ? padding : null
        },

        '&:last-child': {
          paddingLeft: theme.direction === 'rtl' ? padding : null,
          paddingRight: theme.direction === 'ltr' ? padding : null
        }
      };
    }

    return {
      ...ellipsis('100%'),

      display: 'block',
      fontSize,
      lineHeight: getNormalizedValue(theme[`Button_height_${size}`], fontSize),
      ...paddings
    };
  },
  inner: {
    alignItems: 'center',
    display: 'inline-flex',
    justifyContent: 'center',
    maxHeight: '100%',
    width: '100%'
  }
};

const Content = createStyledComponent('span', styles.content);
const Inner = createStyledComponent('span', styles.inner);

function isTypeButton(type: ?string) {
  return ['button', 'submit', 'reset'].indexOf(type) !== -1;
}

function filterProps({ element, type }: Props) {
  // When element is a component, e.g. ReactRouterLink,
  // these are not filtered automatically by rootEl
  const invalidComponentProps = ['primary', 'text', 'variant'];
  const invalidLinkProps =
    element === 'a' && isTypeButton(type) ? ['type'] : [];
  return Array.prototype.concat(invalidComponentProps, invalidLinkProps);
}

/**
 * The Button component represents a clickable button.
 * Buttons draw attention to actions that can be performed in your app.
 * Buttons are used to trigger any sort of event.
 *
 * Always use the appropriate variant for your button, and write a clear, concise label to effectively communicate intention.
 */
export default function Button({
  children,
  element = 'button',
  iconStart,
  iconEnd,
  size = 'large',
  type = 'button',
  variant = 'regular',
  ...restProps
}: Props) {
  const rootProps = {
    size,
    text: children,
    type,
    variant,
    ...restProps
  };

  const Root = createStyledComponent(element, styles.button, {
    filterProps: filterProps({ element, type }),
    includeStyleReset: true,
    rootEl: element
  });

  const iconSize = {
    small: 'medium',
    medium: 'medium',
    large: pxToEm(24),
    jumbo: pxToEm(24)
  };
  const startIcon = iconStart
    ? cloneElement(iconStart, { size: iconSize[size] })
    : null;
  const endIcon = iconEnd
    ? cloneElement(iconEnd, { size: iconSize[size] })
    : null;

  return (
    <Root {...rootProps}>
      <Inner>
        {startIcon}
        {children && <Content size={size}>{children}</Content>}
        {endIcon}
      </Inner>
    </Root>
  );
}
<|endoftext|>


<commit_before>var client_form;
onLoad.queue(function() {
        client_form = new ClientForm({restricted_countries: page.settings.get('restricted_countries'), valid_loginids: page.settings.get('valid_loginids')});
});

pjax_config_page('user/upgrade', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();
            if(page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    fields.forEach(function (element, index, array) {
        var obj = $('#'+element);
        if (obj.length > 0) {
            $('#'+element).attr('disabled', true);
        }
    });
};

var enable_fields_form_submit = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    $('form#openAccForm').submit(function (event) {
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                obj.removeAttr('disabled');
            }
        });
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('#openAccForm fieldset').not("#risk_disclaimer_section").hide();
    }
};

pjax_config_page('user/upgrade/financial|create_account', function() {
    return {
        onLoad: function() {
            upgrade_investment_disabled_field();
            enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<commit_msg>hide form in case we show assessment details<commit_after>var client_form;
onLoad.queue(function() {
        client_form = new ClientForm({restricted_countries: page.settings.get('restricted_countries'), valid_loginids: page.settings.get('valid_loginids')});
});

pjax_config_page('user/upgrade', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();
            if(page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    fields.forEach(function (element, index, array) {
        var obj = $('#'+element);
        if (obj.length > 0) {
            $('#'+element).attr('disabled', true);
        }
    });
};

var enable_fields_form_submit = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    $('form#openAccForm').submit(function (event) {
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                obj.removeAttr('disabled');
            }
        });
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('.formObject fieldset').not("#risk_disclaimer_section").hide();
    }
};

pjax_config_page('user/upgrade/financial|create_account', function() {
    return {
        onLoad: function() {
            upgrade_investment_disabled_field();
            enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});

pjax_config_page('user/assessment', function() {
    return {
        onLoad: function() {
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<|endoftext|>


<commit_before>var client_form;
onLoad.queue(function() {
        client_form = new ClientForm({restricted_countries: page.settings.get('restricted_countries'), valid_loginids: page.settings.get('valid_loginids')});
});

var select_user_country = function() {
    if ($('#residence').length > 0) {
        var restricted_countries = new RegExp(page.settings.get('restricted_countries'));
        var selected_country = $('#residence').val();

        if (selected_country.length > 0) {
            selected_country = (restricted_countries.test(selected_country)) ? '' : selected_country;
            $('#residence').val(selected_country).change();
        } else {
            $.ajax({
                crossDomain: true,
                url: page.url.url_for('country'),
                async: true,
                dataType: "json"
            }).done(function(response) {
                selected_country = (restricted_countries.test(response.country)) ? '' : response.country;
                $('#residence').val(selected_country).change();
            });
        }
    }
};

var enable_residence_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        $('#residence').removeAttr('disabled');
    });
};

pjax_config_page('new_real', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();

            # disable residence selection, if VR acc has residence
            var virtual_residence = $('#virtual_residence');
            if (virtual_residence.length > 0 && virtual_residence.val() == $('#residence').val()) {
                $('#residence').attr('disabled', true);
            }
            enable_residence_form_submit();

            if (page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    fields.forEach(function (element, index, array) {
        var obj = $('#'+element);
        if (obj.length > 0) {
            $('#'+element).attr('disabled', true);
        }
    });
};

var enable_fields_form_submit = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    $('form#openAccForm').submit(function (event) {
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                obj.removeAttr('disabled');
            }
        });
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('.formObject fieldset').not("#risk_disclaimer_section").hide();
    }
};

pjax_config_page('new_financial', function() {
    return {
        onLoad: function() {
            upgrade_investment_disabled_field();
            enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});

pjax_config_page('user/assessment', function() {
    return {
        onLoad: function() {
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<commit_msg>js fx<commit_after>var client_form;
onLoad.queue(function() {
        client_form = new ClientForm({restricted_countries: page.settings.get('restricted_countries'), valid_loginids: page.settings.get('valid_loginids')});
});

var select_user_country = function() {
    if ($('#residence').length > 0) {
        var restricted_countries = new RegExp(page.settings.get('restricted_countries'));
        var selected_country = $('#residence').val();

        if (selected_country.length > 0) {
            selected_country = (restricted_countries.test(selected_country)) ? '' : selected_country;
            $('#residence').val(selected_country).change();
        } else {
            $.ajax({
                crossDomain: true,
                url: page.url.url_for('country'),
                async: true,
                dataType: "json"
            }).done(function(response) {
                selected_country = (restricted_countries.test(response.country)) ? '' : response.country;
                $('#residence').val(selected_country).change();
            });
        }
    }
};

var enable_residence_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        $('#residence').removeAttr('disabled');
    });
};

pjax_config_page('new_real', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();

            // disable residence selection, if VR acc has residence
            var virtual_residence = $('#virtual_residence');
            if (virtual_residence.length > 0 && virtual_residence.val() == $('#residence').val()) {
                $('#residence').attr('disabled', true);
            }
            enable_residence_form_submit();

            if (page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    fields.forEach(function (element, index, array) {
        var obj = $('#'+element);
        if (obj.length > 0) {
            $('#'+element).attr('disabled', true);
        }
    });
};

var enable_fields_form_submit = function () {
    var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
    $('form#openAccForm').submit(function (event) {
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                obj.removeAttr('disabled');
            }
        });
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('.formObject fieldset').not("#risk_disclaimer_section").hide();
    }
};

pjax_config_page('new_financial', function() {
    return {
        onLoad: function() {
            upgrade_investment_disabled_field();
            enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});

pjax_config_page('user/assessment', function() {
    return {
        onLoad: function() {
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<|endoftext|>


<commit_before>import {RequestUtil} from 'mesosphere-shared-reactjs';

import ActionTypes from '../constants/ActionTypes';
import AppDispatcher from './AppDispatcher';
import Config from '../config/Config';

function findWithID(stateObject, listProps, id) {
  let searchItem;
  let length = listProps.length;

  for (let i = 0; i < length; i++) {
    let array = stateObject[listProps[i]];

    if (array) {
      searchItem = array.find(function (element) {
        return element.id === id;
      });

      if (searchItem) {
        return searchItem;
      }
    }
  }

  return null;
}

var TaskDirectoryActions = {
  getDownloadURL(nodeID, path) {
    return `${Config.rootUrl}/agent/${nodeID}/files/download?` +
      `path=${path}`;
  },

  getNodeStateJSON(task, node) {
    let pid, nodePID;

    if (node) {
      pid = node.pid;
    }

    if (pid) {
      nodePID = pid.substring(0, pid.indexOf('@'));
    }

    return `${Config.rootUrl}/agent/${task.slave_id}/${nodePID}/state`;
  },

  getInnerPath(nodeState, task, innerPath) {
    innerPath = innerPath || '';

    // Search frameworks
    let framework = findWithID(
      nodeState,
      ['frameworks', 'completed_frameworks'],
      task.framework_id
    );

    if (!framework) {
      return null;
    }

    // Search executors
    let executor = findWithID(
      framework,
      ['executors', 'completed_executors'],
      task.executor_id || task.id // Fallback to task id, if no executor id
    );

    if (!executor) {
      return null;
    }

    return `${executor.directory}/${innerPath}`;
  },

  fetchNodeState: RequestUtil.debounceOnError(
    Config.getRefreshRate(),
    function (resolve, reject) {
      return function (task, node, cb) {
        return RequestUtil.json({
          url: TaskDirectoryActions.getNodeStateJSON(task, node),
          timeout: 5000,
          success(response) {
            resolve();
            cb(response);
          },
          error(xhr) {
            if (xhr.statusText === 'abort') {
              resolve();
              return;
            }

            AppDispatcher.handleServerAction({
              type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR,
              data: xhr.message
            });

            reject();
          }
        });
      };
    },
    {delayAfterCount: Config.delayAfterErrorCount}
  ),

  fetchDirectory(task, innerPath, nodeState) {
    let path = TaskDirectoryActions.getInnerPath(nodeState, task, innerPath);
    if (path == null) {
      AppDispatcher.handleServerAction({
        type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR
      });
      return;
    }

    RequestUtil.json({
      url: `${Config.rootUrl}/agent/${task.slave_id}/files/browse`,
      data: {path},
      success(directory) {
        AppDispatcher.handleServerAction({
          type: ActionTypes.REQUEST_TASK_DIRECTORY_SUCCESS,
          data: directory,
          innerPath,
          taskID: task.id
        });
      },
      error(xhr) {
        if (xhr.statusText === 'abort') {
          return;
        }

        AppDispatcher.handleServerAction({
          type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR,
          data: xhr.message,
          taskID: task.id
        });
      }
    });
  }
};

module.exports = TaskDirectoryActions;
<commit_msg>Integrate the Mesos state task path util<commit_after>import {RequestUtil} from 'mesosphere-shared-reactjs';

import ActionTypes from '../constants/ActionTypes';
import AppDispatcher from './AppDispatcher';
import Config from '../config/Config';
import MesosStateUtil from '../utils/MesosStateUtil';

function findWithID(stateObject, listProps, id) {
  let searchItem;
  let length = listProps.length;

  for (let i = 0; i < length; i++) {
    let array = stateObject[listProps[i]];

    if (array) {
      searchItem = array.find(function (element) {
        return element.id === id;
      });

      if (searchItem) {
        return searchItem;
      }
    }
  }

  return null;
}

var TaskDirectoryActions = {
  getDownloadURL(nodeID, path) {
    return `${Config.rootUrl}/agent/${nodeID}/files/download?` +
      `path=${path}`;
  },

  getNodeStateJSON(task, node) {
    let pid, nodePID;

    if (node) {
      pid = node.pid;
    }

    if (pid) {
      nodePID = pid.substring(0, pid.indexOf('@'));
    }

    return `${Config.rootUrl}/agent/${task.slave_id}/${nodePID}/state`;
  },

  getInnerPath(nodeState, task, innerPath) {
    innerPath = innerPath || '';

    // Search frameworks
    let framework = findWithID(
      nodeState,
      ['frameworks', 'completed_frameworks'],
      task.framework_id
    );

    if (!framework) {
      return null;
    }

    // Search executors
    let executor = findWithID(
      framework,
      ['executors', 'completed_executors'],
      task.executor_id || task.id // Fallback to task id, if no executor id
    );

    if (!executor) {
      return null;
    }

    return `${executor.directory}/${innerPath}`;
  },

  fetchNodeState: RequestUtil.debounceOnError(
    Config.getRefreshRate(),
    function (resolve, reject) {
      return function (task, node, cb) {
        return RequestUtil.json({
          url: TaskDirectoryActions.getNodeStateJSON(task, node),
          timeout: 5000,
          success(response) {
            resolve();
            cb(response);
          },
          error(xhr) {
            if (xhr.statusText === 'abort') {
              resolve();
              return;
            }

            AppDispatcher.handleServerAction({
              type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR,
              data: xhr.message
            });

            reject();
          }
        });
      };
    },
    {delayAfterCount: Config.delayAfterErrorCount}
  ),

  fetchDirectory(task, innerPath, nodeState) {
    let path = MesosStateUtil.getTaskPath(nodeState, task, innerPath);
    if (path == null) {
      AppDispatcher.handleServerAction({
        type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR
      });
      return;
    }

    RequestUtil.json({
      url: `${Config.rootUrl}/agent/${task.slave_id}/files/browse`,
      data: {path},
      success(directory) {
        AppDispatcher.handleServerAction({
          type: ActionTypes.REQUEST_TASK_DIRECTORY_SUCCESS,
          data: directory,
          innerPath,
          taskID: task.id
        });
      },
      error(xhr) {
        if (xhr.statusText === 'abort') {
          return;
        }

        AppDispatcher.handleServerAction({
          type: ActionTypes.REQUEST_TASK_DIRECTORY_ERROR,
          data: xhr.message,
          taskID: task.id
        });
      }
    });
  }
};

module.exports = TaskDirectoryActions;
<|endoftext|>


<commit_before>/**
 * @file Drawer component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import query from 'dom-helpers/query';

import PositionPop from '../_PositionPop';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Dom from '../_vendors/Dom';
import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import PopManagement from '../_vendors/PopManagement';

class Drawer extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.closeTimeout = null;

    }

    clearCloseTimeout = () => {
        if (this.closeTimeout) {
            clearTimeout(this.closeTimeout);
            this.closeTimeout = null;
        }
    };

    triggerHandler = (el, triggerEl, drawerEl, currentVisible, isBlurClose) => {

        // el is missing
        if (el && !query.contains(document, el)) {
            return currentVisible;
        }

        if ((triggerEl && el && query.contains(triggerEl, el))
            || (drawerEl && el && query.contains(drawerEl, el))) {
            return currentVisible;
        }

        return isBlurClose ? false : currentVisible;

    };

    closeHandler = e => {

        const {visible, isBlurClose, triggerEl, triggerHandler, onRequestClose} = this.props,
            drawerEl = findDOMNode(this.refs.drawerContent);

        if (!visible || !triggerEl) {
            return;
        }

        let currVisible;

        if (triggerHandler) {
            currVisible = triggerHandler(e.target, triggerEl, drawerEl, visible, isBlurClose);
        } else if (!Dom.isParent(e.target)) {
            currVisible = this.triggerHandler(e.target, triggerEl, drawerEl, visible, isBlurClose);
        }

        if (currVisible === false) {
            this.clearCloseTimeout();
            this.closeTimeout = setTimeout(() => {
                onRequestClose && onRequestClose(e);
            });
        }

    };

    renderHandler = (...args) => {

        PopManagement.push(this);

        const {onRender} = this.props;
        onRender && onRender(...args);

    };

    destroyHandler = (...args) => {

        PopManagement.pop(this);

        const {onDestroy} = this.props;
        onDestroy && onDestroy(...args);

    };

    componentDidMount() {
        Event.addEvent(document, 'click', this.closeHandler);
    }

    componentWillUnmount() {
        this.clearCloseTimeout();
        Event.removeEvent(document, 'click', this.closeHandler);
    }

    render() {

        const {

                className,

                // not passing down these props
                triggerEl, isBlurClose, isEscClose, onRender, onRequestClose,

                ...restProps

            } = this.props,

            drawerClassName = classNames('drawer', {
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         className={drawerClassName}
                         container={
                             <Paper ref="drawerContent"
                                    depth={6}></Paper>
                         }
                         onRender={this.renderHandler}
                         onDestroy={this.destroyHandler}/>
        );

    }

}

Drawer.propTypes = {

    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The css class name of the modal.
     */
    modalClassName: PropTypes.string,

    /**
     * The styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The drawer alignment.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    triggerEl: PropTypes.object,

    /**
     * If true,the element will disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true,drawer box will display.
     */
    visible: PropTypes.bool,

    /**
     * If true,the pop-up box will be displayed in the mask layer, or the pop-up box will appear below the element.
     */
    showModal: PropTypes.bool,

    /**
     * If true,when press down mouse the pop-up box will closed.
     */
    isBlurClose: PropTypes.bool,

    isEscClose: PropTypes.bool,

    /**
     * The function of drawer render.
     */
    onRender: PropTypes.func,

    triggerHandler: PropTypes.func,

    /**
     * The function that trigger when click submit.
     */
    onRequestClose: PropTypes.func

};

Drawer.defaultProps = {

    position: Position.LEFT,
    disabled: false,
    visible: false,
    showModal: true,

    isBlurClose: true,
    isEscClose: true

};

export default Drawer;
<commit_msg>update Drawer<commit_after>/**
 * @file Drawer component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import query from 'dom-helpers/query';

import PositionPop from '../_PositionPop';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Dom from '../_vendors/Dom';
import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import PopManagement from '../_vendors/PopManagement';

class Drawer extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.closeTimeout = null;

    }

    clearCloseTimeout = () => {
        if (this.closeTimeout) {
            clearTimeout(this.closeTimeout);
            this.closeTimeout = null;
        }
    };

    triggerHandler = (el, triggerEl, drawerEl, currentVisible, isBlurClose) => {

        // el is missing
        if (el && !query.contains(document, el)) {
            return currentVisible;
        }

        if ((triggerEl && el && query.contains(triggerEl, el))
            || (drawerEl && el && query.contains(drawerEl, el))) {
            return currentVisible;
        }

        return isBlurClose ? false : currentVisible;

    };

    closeHandler = e => {

        const {visible, isBlurClose, triggerEl, triggerHandler, onRequestClose} = this.props,
            drawerEl = findDOMNode(this.refs.drawerContent);

        if (!visible || !triggerEl) {
            return;
        }

        let currVisible;

        if (triggerHandler) {
            currVisible = triggerHandler(e.target, triggerEl, drawerEl, visible, isBlurClose);
        } else if (!Dom.isParent(e.target)) {
            currVisible = this.triggerHandler(e.target, triggerEl, drawerEl, visible, isBlurClose);
        }

        if (currVisible === false) {
            this.clearCloseTimeout();
            this.closeTimeout = setTimeout(() => {
                onRequestClose && onRequestClose(e);
            });
        }

    };

    renderHandler = (...args) => {

        PopManagement.push(this, {
            shouldLockBody: this.props.showModal
        });

        const {onRender} = this.props;
        onRender && onRender(...args);

    };

    destroyHandler = (...args) => {

        PopManagement.pop(this);

        const {onDestroy} = this.props;
        onDestroy && onDestroy(...args);

    };

    componentDidMount() {
        Event.addEvent(document, 'click', this.closeHandler);
    }

    componentWillUnmount() {
        this.clearCloseTimeout();
        Event.removeEvent(document, 'click', this.closeHandler);
    }

    render() {

        const {

                className,

                // not passing down these props
                triggerEl, isBlurClose, isEscClose, onRender, onRequestClose,

                ...restProps

            } = this.props,

            drawerClassName = classNames('drawer', {
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         className={drawerClassName}
                         container={
                             <Paper ref="drawerContent"
                                    depth={6}></Paper>
                         }
                         onRender={this.renderHandler}
                         onDestroy={this.destroyHandler}/>
        );

    }

}

Drawer.propTypes = {

    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The css class name of the modal.
     */
    modalClassName: PropTypes.string,

    /**
     * The styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The drawer alignment.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    triggerEl: PropTypes.object,

    /**
     * If true,the element will disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true,drawer box will display.
     */
    visible: PropTypes.bool,

    /**
     * If true,the pop-up box will be displayed in the mask layer, or the pop-up box will appear below the element.
     */
    showModal: PropTypes.bool,

    /**
     * If true,when press down mouse the pop-up box will closed.
     */
    isBlurClose: PropTypes.bool,

    isEscClose: PropTypes.bool,

    /**
     * The function of drawer render.
     */
    onRender: PropTypes.func,

    triggerHandler: PropTypes.func,

    /**
     * The function that trigger when click submit.
     */
    onRequestClose: PropTypes.func

};

Drawer.defaultProps = {

    position: Position.LEFT,
    disabled: false,
    visible: false,
    showModal: true,

    isBlurClose: true,
    isEscClose: true

};

export default Drawer;
<|endoftext|>


<commit_before>function FifteenPuzzle() {

	var imageURL = "";

	var size = 5;

	var self = this;

	this.imageURLInput = new Binding({

		init: function(element) {

			element.value = imageURL;

			element.addEventListener("change", function() {

				imageURL = element.value;
				self.puzzle = new Puzzle(imageURL, size);
			});
		}
	});

	this.sizeInput = new Binding({

		init: function(element) {

			element.value = size;

			element.addEventListener("change", function() {

				size = ~~element.value;
				self.puzzle = new Puzzle(imageURL, size);
			});
		}
	});

	this.puzzle = new Puzzle(imageURL, size);

	function Puzzle(imageURL, size) {

		this.tiles = [];

		var numberOfTiles = Math.floor(size * size - 1);

		for (var i = 0; i < numberOfTiles; i++) {

			this.tiles.push(new Tile(i));
		}

		this.tiles.push(new Space());

		var tiles = this.tiles;

		var shuffles = Math.min(20 * size * size * size, 10000);

		function shuffleTiles(remainingShuffles) {

			if (remainingShuffles > 0) {

				var index = getRandomTileIndex();

				tiles[index].trySwap();

				setTimeout(function () {

					shuffleTiles(--remainingShuffles);
				}, Math.floor(5000 / shuffles));
			}
		}

		if (imageURL) {

			shuffleTiles(shuffles);
		}

		function getRandomTileIndex() {

			return Math.floor(Math.random() * size * size);
		}

		function Tile(number) {

			var self = this;

			this.trySwap = function () {

				if (isAdjacentToSpace()) {

					var spaceIndex = getSpaceIndex();
					var myIndex = getIndex();

					tiles.splice(myIndex, 1, new Space());
					tiles.splice(spaceIndex, 1, this);
				}
			};

			this.isSpace = function () {

				return false;
			};

			this.tile = new Binding({

				click: function () {

					this.trySwap()
				},
				init: function (element) {

					var tileWidth = (700 / size) - 2;
					element.style.width = tileWidth + "px";
					element.style.height = tileWidth + "px";

					var image = element.querySelector("img");
					var horizontalOffset = (number % size) * -100;
					var verticalOffset = Math.floor(number / size) * -100;

					image.style.marginLeft = horizontalOffset + "%";
					image.style.marginTop = verticalOffset + "%";
					image.style.height = (size * 100) + "%";
					image.style.width = (size * 100) + "%";
					image.src = imageURL;
				}
			});

			function getSpaceIndex() {

				for (var i = 0; i < tiles.length; i++) {

					if (tiles[i].isSpace()) {

						return i;
					}
				}
			}

			function isAdjacentToSpace() {

				var myIndex = getIndex();
				var neighbours = getNeighbours(myIndex);
				var isAdjacentToSpace = false;

				neighbours.forEach(function(index) {

					var neighbour = tiles[myIndex + index];

					if (neighbour && neighbour.isSpace()) {

						isAdjacentToSpace = true;
					}
				});

				return isAdjacentToSpace;
			}

			function getNeighbours(myIndex) {

				var neighbours = [size, -size];

				if (myIndex % size) {

					neighbours.push(-1);
				}

				if ((myIndex + 1) % size) {

					neighbours.push(1);
				}

				return neighbours;
			}

			function getIndex() {

				for (var i = 0; i < tiles.length; i++) {

					if (self == tiles[i]) {

						return i;
					}
				}
			}
		}

		function Space() {

			this.tile = new Binding({

				init: function (element) {

					var tileWidth = (700 / size) - 2;
					element.style.width = tileWidth + "px";
					element.style.height = tileWidth + "px";
				}
			});

			this.trySwap = function () {};

			this.isSpace = function () {

				return true;
			};
		}
	}
}

document.addEventListener("DOMContentLoaded", function () {

	new BindingRoot(fifteenPuzzle = new FifteenPuzzle());
});
<commit_msg>Refactor inputs.<commit_after>function FifteenPuzzle() {

	var imageURL = "";

	var size = 5;

	this.puzzle = new Puzzle(imageURL, size);

	this.imageURLInput = new Binding({

		value: function(value) {

			if (value) {

				imageURL = value;
				this.puzzle = new Puzzle(imageURL, size);
			}

			return imageURL;
		}
	});

	this.sizeInput = new Binding({

		value: function(value) {

			if (value) {

				size = ~~value;
				this.puzzle = new Puzzle(imageURL, size);
			}

			return size;
		}
	});

	function Puzzle(imageURL, size) {

		this.tiles = [];

		var numberOfTiles = Math.floor(size * size - 1);

		for (var i = 0; i < numberOfTiles; i++) {

			this.tiles.push(new Tile(i));
		}

		this.tiles.push(new Space());

		var tiles = this.tiles;

		var shuffles = Math.min(20 * size * size * size, 10000);

		function shuffleTiles(remainingShuffles) {

			if (remainingShuffles > 0) {

				var index = getRandomTileIndex();

				tiles[index].trySwap();

				setTimeout(function () {

					shuffleTiles(--remainingShuffles);
				}, Math.floor(5000 / shuffles));
			}
		}

		if (imageURL) {

			shuffleTiles(shuffles);
		}

		function getRandomTileIndex() {

			return Math.floor(Math.random() * size * size);
		}

		function Tile(number) {

			var self = this;

			this.trySwap = function () {

				if (isAdjacentToSpace()) {

					var spaceIndex = getSpaceIndex();
					var myIndex = getIndex();

					tiles.splice(myIndex, 1, new Space());
					tiles.splice(spaceIndex, 1, this);
				}
			};

			this.isSpace = function () {

				return false;
			};

			this.tile = new Binding({

				click: function () {

					this.trySwap()
				},
				init: function (element) {

					var tileWidth = (700 / size) - 2;
					element.style.width = tileWidth + "px";
					element.style.height = tileWidth + "px";

					var image = element.querySelector("img");
					var horizontalOffset = (number % size) * -100;
					var verticalOffset = Math.floor(number / size) * -100;

					image.style.marginLeft = horizontalOffset + "%";
					image.style.marginTop = verticalOffset + "%";
					image.style.height = (size * 100) + "%";
					image.style.width = (size * 100) + "%";
					image.src = imageURL;
				}
			});

			function getSpaceIndex() {

				for (var i = 0; i < tiles.length; i++) {

					if (tiles[i].isSpace()) {

						return i;
					}
				}
			}

			function isAdjacentToSpace() {

				var myIndex = getIndex();
				var neighbours = getNeighbours(myIndex);
				var isAdjacentToSpace = false;

				neighbours.forEach(function(index) {

					var neighbour = tiles[myIndex + index];

					if (neighbour && neighbour.isSpace()) {

						isAdjacentToSpace = true;
					}
				});

				return isAdjacentToSpace;
			}

			function getNeighbours(myIndex) {

				var neighbours = [size, -size];

				if (myIndex % size) {

					neighbours.push(-1);
				}

				if ((myIndex + 1) % size) {

					neighbours.push(1);
				}

				return neighbours;
			}

			function getIndex() {

				for (var i = 0; i < tiles.length; i++) {

					if (self == tiles[i]) {

						return i;
					}
				}
			}
		}

		function Space() {

			this.tile = new Binding({

				init: function (element) {

					var tileWidth = (700 / size) - 2;
					element.style.width = tileWidth + "px";
					element.style.height = tileWidth + "px";
				}
			});

			this.trySwap = function () {};

			this.isSpace = function () {

				return true;
			};
		}
	}
}

document.addEventListener("DOMContentLoaded", function () {

	new BindingRoot(fifteenPuzzle = new FifteenPuzzle());
});
<|endoftext|>