<commit_before>'use strict';

/*
  This module was based http://code.realcrowd.com/on-the-bleeding-edge-advanced-angularjs-form-validation/
*/

angular.module('ui.bootstrap.validation', [])
.directive('uiValidationSubmit', ['$parse', function ($parse) {
	return {
		restrict: 'A',
		require: ['uiValidationSubmit', '?form'],
		controller: [function () {
			this.attempted = false;

			this.setAttempted = function() {
				this.attempted = true;
			};
		}],
		link: function(scope, formElement, attrs, controllers) {
			var submitController = controllers[0];
			var formController = (controllers.length > 1) ? controllers[1] : null;

			var fn = $parse(attrs.uiValidationSubmit);

			formElement.bind('submit', function () {
				submitController.setAttempted();
				if (!scope.$$phase) {
					scope.$apply();
				}

				if (!formController.$valid) {
					return false;
				}

				scope.$apply(function() {
					fn(scope, {$event:event});
				});
			});
		}
	};
}])
.directive('uiValidationShowErrors', [function () {
	return {
		restrict: 'A',
		require: [
			'^form',
			'^?uiValidationSubmit'
		],
		scope: { },
		link: function (scope, element, attrs, controllers) {
			if(!element.hasClass('form-group')) {
				throw 'ui-validation-show-errors element requires \'form-group\' class';
			}

			var formCtrl = controllers[0];

			if(!formCtrl) {
				throw 'ui-validation-show-errors requires a controller associated to this form';
			}

			var submitCtrl = (controllers.length > 1) ? controllers[1] : null;

			var inputElement = element[0].querySelector('input[name],select[name],textarea[name]');

			if(!inputElement)	{
				throw 'ui-validation-show-errors requires a child input/select/textarea element with a \'name\' attribute';
			}

			var fieldCtrl = formCtrl[inputElement.name];

			scope.$watch(function(){
				return fieldCtrl.$invalid && (!submitCtrl || submitCtrl.attempted);
			}, function(needsAttention) {
				if(needsAttention) {
					element.addClass('has-error');
				} else {
					element.removeClass('has-error');
				}
			});
		}
	};
}])
.directive('uiValidationErrorMessages', ['$compile', function ($compile) {
	return {
		restrict: 'E',
		require: '^form',
		replace: true,
		templateUrl: 'templates/form-validation/error-messages.html',
		scope: {},
		link: function(scope, element, attrs, formCtrl) {
			var formGroup = element.parent();
			var inputElement = formGroup[0].querySelector('input[name],select[name],textarea[name]');

			if(!inputElement)	{
				throw 'ui-validation-error-messages requires a sibling input/select/textarea element with a \'name\' attribute';
			}

			scope.fieldCtrl = formCtrl[inputElement.name];
			var angularElement = angular.element(inputElement);
			scope.minlength = angularElement.attr('ng-minlength');
			scope.min = angularElement.attr('min');
			scope.max = angularElement.attr('max');

			scope.errorMessages = {
				'required': 'Campo de preenchimento obrigatório',
				'min': 'Valor mínimo: '+scope.min,
				'max': 'Valor mínimo: '+scope.max,
				'minlength': 'Tamanho mínimo: '+scope.minlength+' caracteres',
				'email': 'Email inválido',
			};
		}
	};
}])
.directive('uiCustomErrorMessage', [function () {
	return {
		restrict: 'E',
		replace: true,
		link: function (scope, element, attrs) {

		}
	};
}])
.run(['$templateCache', function($templateCache) {
	$templateCache.put('templates/form-validation/error-messages.html',
		'
' +
		'	{{errorMessages[errorType]}}' +
		'
'
	);
}]);<commit_msg>Fixed form submit<commit_after>'use strict';

/*
  This module was based http://code.realcrowd.com/on-the-bleeding-edge-advanced-angularjs-form-validation/
*/

angular.module('ui.bootstrap.validation', [])
.directive('uiValidationSubmit', ['$parse', function ($parse) {
	return {
		restrict: 'A',
		require: ['uiValidationSubmit', '?form'],
		controller: [function () {
			this.attempted = false;

			this.setAttempted = function() {
				this.attempted = true;
			};
		}],
		link: function(scope, formElement, attrs, controllers) {
			var submitController = controllers[0];
			var formController = (controllers.length > 1) ? controllers[1] : null;

			var fn = $parse(attrs.uiValidationSubmit);

			formElement.bind('submit', function (event) {
				submitController.setAttempted();
				if (!scope.$$phase) {
					scope.$apply();
				}

				if (!formController.$valid) {
					return false;
				}

				scope.$apply(function() {
					fn(scope, {
						$event: event
					});
				});
			});
		}
	};
}])
.directive('uiValidationShowErrors', [function () {
	return {
		restrict: 'A',
		require: [
			'^form',
			'^?uiValidationSubmit'
		],
		scope: { },
		link: function (scope, element, attrs, controllers) {
			if(!element.hasClass('form-group')) {
				throw 'ui-validation-show-errors element requires \'form-group\' class';
			}

			var formCtrl = controllers[0];

			if(!formCtrl) {
				throw 'ui-validation-show-errors requires a controller associated to this form';
			}

			var submitCtrl = (controllers.length > 1) ? controllers[1] : null;

			var inputElement = element[0].querySelector('input[name],select[name],textarea[name]');

			if(!inputElement)	{
				throw 'ui-validation-show-errors requires a child input/select/textarea element with a \'name\' attribute';
			}

			var fieldCtrl = formCtrl[inputElement.name];

			scope.$watch(function(){
				return fieldCtrl.$invalid && (!submitCtrl || submitCtrl.attempted);
			}, function(needsAttention) {
				if(needsAttention) {
					element.addClass('has-error');
				} else {
					element.removeClass('has-error');
				}
			});
		}
	};
}])
.directive('uiValidationErrorMessages', ['$compile', function ($compile) {
	return {
		restrict: 'E',
		require: '^form',
		replace: true,
		templateUrl: 'templates/form-validation/error-messages.html',
		scope: {},
		link: function(scope, element, attrs, formCtrl) {
			var formGroup = element.parent();
			var inputElement = formGroup[0].querySelector('input[name],select[name],textarea[name]');

			if(!inputElement)	{
				throw 'ui-validation-error-messages requires a sibling input/select/textarea element with a \'name\' attribute';
			}

			scope.fieldCtrl = formCtrl[inputElement.name];
			var angularElement = angular.element(inputElement);
			scope.minlength = angularElement.attr('ng-minlength');
			scope.min = angularElement.attr('min');
			scope.max = angularElement.attr('max');

			scope.errorMessages = {
				'required': 'Campo de preenchimento obrigatório',
				'min': 'Valor mínimo: '+scope.min,
				'max': 'Valor mínimo: '+scope.max,
				'minlength': 'Tamanho mínimo: '+scope.minlength+' caracteres',
				'email': 'Email inválido',
			};
		}
	};
}])
.directive('uiCustomErrorMessage', [function () {
	return {
		restrict: 'E',
		replace: true,
		link: function (scope, element, attrs) {

		}
	};
}])
.run(['$templateCache', function($templateCache) {
	$templateCache.put('templates/form-validation/error-messages.html',
		'
' +
		'	{{errorMessages[errorType]}}' +
		'
'
	);
}]);<|endoftext|>


<commit_before>/**************************************************************************
	Copyright (c) 2001-2003 Geir Landrц (drop@destroydrop.com)
	JavaScript Tree - www.destroydrop.com/hjavascripts/tree/
	Version 0.96

	This script can be used freely as long as all copyright messages are
	intact.
**************************************************************************/

// Arrays for nodes and icons
var nodes		= new Array();;
var openNodes	= new Array();
var icons		= new Array(6);

// Loads all icons that are used in the tree
function preloadIcons() {
	icons[0] = new Image();
	icons[0].src = "web/images/plus.gif";
	icons[1] = new Image();
	icons[1].src = "web/images/plusbottom.gif";
	icons[2] = new Image();
	icons[2].src = "web/images/minus.gif";
	icons[3] = new Image();
	icons[3].src = "web/images/minusbottom.gif";
	icons[4] = new Image();
	icons[4].src = "web/images/folder.gif";
	icons[5] = new Image();
	icons[5].src = "web/images/folderopen.gif";
}
// Create the tree
function createTree(arrName, startNode, openNode) {
	nodes = arrName;
	if (nodes.length > 0) {
		preloadIcons();
		if (startNode == null) startNode = 0;
		if (openNode != 0 || openNode != null) setOpenNodes(openNode);

		if (startNode !=0) {
			var nodeValues = nodes[getArrayId(startNode)].split("|");
			document.write("" + nodeValues[2] + "
");
		} else document.write("Справка по РДО
");

		var recursedNodes = new Array();
		addNode(startNode, recursedNodes);
	}
}
// Returns the position of a node in the array
function getArrayId(node) {
	for (i=0; i<nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[0]==node) return i;
	}
}
// Puts in array nodes that will be open
function setOpenNodes(openNode) {
	for (i=0; i<nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[0]==openNode) {
			openNodes.push(nodeValues[0]);
			setOpenNodes(nodeValues[1]);
		}
	}
}
// Checks if a node is open
function isNodeOpen(node) {
	for (i=0; i<openNodes.length; i++)
		if (openNodes[i]==node) return true;
	return false;
}
// Checks if a node has any children
function hasChildNode(parentNode) {
	for (i=0; i< nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode) return true;
	}
	return false;
}
// Checks if a node is the last sibling
function lastSibling (node, parentNode) {
	var lastChild = 0;
	for (i=0; i< nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode)
			lastChild = nodeValues[0];
	}
	if (lastChild==node) return true;
	return false;
}
// Adds a new node to the tree
function addNode(parentNode, recursedNodes) {
	for (var i = 0; i < nodes.length; i++) {

		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode) {

			var ls	= lastSibling(nodeValues[0], nodeValues[1]);
			var hcn	= hasChildNode(nodeValues[0]);
			var ino = isNodeOpen(nodeValues[0]);

			// Write out line & empty icons
			for (g=0; g<recursedNodes.length; g++) {
				if (recursedNodes[g] == 1) document.write("");
				else  document.write("");
			}

			// put in array line & empty icons
			if (ls) recursedNodes.push(0);
			else recursedNodes.push(1);

			// Write out join icons
			if (hcn) {
				if (ls) {
					document.write("");
				} else {
					document.write("");
				}
			} else {
				if (ls) document.write("");
				else document.write("");
			}

			// Start link
			document.write("");

			// Write out folder & page icons
			if (hcn) {
				document.write("");
			} else document.write("");

			// Write out node name
			document.write(nodeValues[2]);

			// End link
			document.write("
");

			// If node has children write out divs and go deeper
			if (hcn) {
				document.write("
");
				addNode(nodeValues[0], recursedNodes);
				document.write("
");
			}

			// remove last line or empty icon
			recursedNodes.pop();
		}
	}
}
// Opens or closes a node
function oc(node, bottom) {
	var theDiv = document.getElementById("div" + node);
	var theJoin	= document.getElementById("join" + node);
	var theIcon = document.getElementById("icon" + node);

	if (theDiv.style.display == 'none') {
		if (bottom==1) theJoin.src = icons[3].src;
		else theJoin.src = icons[2].src;
		theIcon.src = icons[5].src;
		theDiv.style.display = '';
	} else {
		if (bottom==1) theJoin.src = icons[1].src;
		else theJoin.src = icons[0].src;
		theIcon.src = icons[4].src;
		theDiv.style.display = 'none';
	}
}
// Push and pop not implemented in IE
if(!Array.prototype.push) {
	function array_push() {
		for(var i=0;i<arguments.length;i++)
			this[this.length]=arguments[i];
		return this.length;
	}
	Array.prototype.push = array_push;
}
if(!Array.prototype.pop) {
	function array_pop(){
		lastElement = this[this.length-1];
		this.length = Math.max(this.length-1,0);
		return lastElement;
	}
	Array.prototype.pop = array_pop;
}
<commit_msg> - коррекция скрипта: избавление от некрасивости<commit_after>/**************************************************************************
	Copyright (c) 2001-2003 Geir Landrц (drop@destroydrop.com)
	JavaScript Tree - www.destroydrop.com/hjavascripts/tree/
	Version 0.96

	This script can be used freely as long as all copyright messages are
	intact.
**************************************************************************/

// Arrays for nodes and icons
var nodes		= new Array();;
var openNodes	= new Array();
var icons		= new Array(6);

// Loads all icons that are used in the tree
function preloadIcons() {
	icons[0] = new Image();
	icons[0].src = "web/images/plus.gif";
	icons[1] = new Image();
	icons[1].src = "web/images/plusbottom.gif";
	icons[2] = new Image();
	icons[2].src = "web/images/minus.gif";
	icons[3] = new Image();
	icons[3].src = "web/images/minusbottom.gif";
	icons[4] = new Image();
	icons[4].src = "web/images/folder.gif";
	icons[5] = new Image();
	icons[5].src = "web/images/folderopen.gif";
}
// Create the tree
function createTree(arrName, startNode, openNode) {
	nodes = arrName;
	if (nodes.length > 0) {
		preloadIcons();
		if (startNode == null) startNode = 0;
		if (openNode != 0 || openNode != null) setOpenNodes(openNode);

		if (startNode !=0) {
			var nodeValues = nodes[getArrayId(startNode)].split("|");
			document.write("" + nodeValues[2] + "
");
		} else document.write("Справка по РДО
");

		var recursedNodes = new Array();
		addNode(startNode, recursedNodes);
	}
}
// Returns the position of a node in the array
function getArrayId(node) {
	for (i=0; i<nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[0]==node) return i;
	}
}
// Puts in array nodes that will be open
function setOpenNodes(openNode) {
	for (i=0; i<nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[0]==openNode) {
			openNodes.push(nodeValues[0]);
			setOpenNodes(nodeValues[1]);
		}
	}
}
// Checks if a node is open
function isNodeOpen(node) {
	for (i=0; i<openNodes.length; i++)
		if (openNodes[i]==node) return true;
	return false;
}
// Checks if a node has any children
function hasChildNode(parentNode) {
	for (i=0; i< nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode) return true;
	}
	return false;
}
// Checks if a node is the last sibling
function lastSibling (node, parentNode) {
	var lastChild = 0;
	for (i=0; i< nodes.length; i++) {
		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode)
			lastChild = nodeValues[0];
	}
	if (lastChild==node) return true;
	return false;
}
// Adds a new node to the tree
function addNode(parentNode, recursedNodes) {
	for (var i = 0; i < nodes.length; i++) {

		var nodeValues = nodes[i].split("|");
		if (nodeValues[1] == parentNode) {

			var ls	= lastSibling(nodeValues[0], nodeValues[1]);
			var hcn	= hasChildNode(nodeValues[0]);
			var ino = isNodeOpen(nodeValues[0]);

			// Write out line & empty icons
			for (g=0; g<recursedNodes.length; g++) {
				if (recursedNodes[g] == 1) document.write("");
				else  document.write("");
			}

			// put in array line & empty icons
			if (ls) recursedNodes.push(0);
			else recursedNodes.push(1);

			// Write out join icons
			if (hcn) {
				if (ls) {
					document.write("");
				} else {
					document.write("");
				}
			} else {
				if (ls) document.write("");
				else document.write("");
			}

			// Start link
			if ((nodeValues[1] == "0") && (hasChildNode(nodeValues[0])))
				document.write("");
			else
				document.write("");

			// Write out folder & page icons
			if (hcn) {
				document.write("");
			} else document.write("");

			// Write out node name
			document.write(nodeValues[2]);

			// End link
			document.write("
");

			// If node has children write out divs and go deeper
			if (hcn) {
				document.write("
");
				addNode(nodeValues[0], recursedNodes);
				document.write("
");
			}

			// remove last line or empty icon
			recursedNodes.pop();
		}
	}
}
// Opens or closes a node
function oc(node, bottom) {
	var theDiv = document.getElementById("div" + node);
	var theJoin	= document.getElementById("join" + node);
	var theIcon = document.getElementById("icon" + node);

	if (theDiv.style.display == 'none') {
		if (bottom==1) theJoin.src = icons[3].src;
		else theJoin.src = icons[2].src;
		theIcon.src = icons[5].src;
		theDiv.style.display = '';
	} else {
		if (bottom==1) theJoin.src = icons[1].src;
		else theJoin.src = icons[0].src;
		theIcon.src = icons[4].src;
		theDiv.style.display = 'none';
	}
}
// Push and pop not implemented in IE
if(!Array.prototype.push) {
	function array_push() {
		for(var i=0;i<arguments.length;i++)
			this[this.length]=arguments[i];
		return this.length;
	}
	Array.prototype.push = array_push;
}
if(!Array.prototype.pop) {
	function array_pop(){
		lastElement = this[this.length-1];
		this.length = Math.max(this.length-1,0);
		return lastElement;
	}
	Array.prototype.pop = array_pop;
}<|endoftext|>


<commit_before>(function () {
    "use strict";

    jsPlumb.ready(function () {

        jsPlumb.setContainer("container");
        jsPlumb.importDefaults({
            ConnectionsDetachable: false
        });

        function exportAsImage() {
            alert("export");
        }

        function addRectangle() {
            alert("add rect");
        }

        function addCircle() {
            alert("add circle");
        }

        function initRectangles() {
            var rectLeftId = "rectLeft";
            var rectRightId = "rectRight";
            var commonConnectStyle = {
                anchors: ["Right", "Left"],
                type: "Straight"

            };

            jsPlumb.draggable([rectLeftId, rectRightId], {
                containment: true
            });

            jsPlumb.connect({
                source: rectLeftId,
                target: rectRightId,
                deleteEndpointsOnDetach: false,
                connector: ["Straight"],
                endpointStyle: {fill: "black"},
                endpoints:["Blank","Blank"]

            }, commonConnectStyle);

        }

        function initCircles() {
            var circleLeftId = "circleLeft";
            var circleRightId = "circleRight";
            var commonConnectStyle = {
                anchors: ["Right", "Left"]
            };
            jsPlumb.draggable([circleLeftId, circleRightId], {
                containment: true
            });

            jsPlumb.connect({
                source: circleLeftId,
                target: circleRightId,
                deleteEndpointsOnDetach: false,
                connector: ["Straight"],
                endpoints:["Blank","Blank"]

            }, commonConnectStyle);
        }

        function main() {
            initRectangles();
            initCircles();
            $("#addRectBtn").click(addRectangle);
            $("#addCircleBtn").click(addCircle);
            $("#exportBtn").click(exportAsImage);
        }

        main();
    });

})();
<commit_msg>Changed style of lines #BPMN4T-35<commit_after>(function () {
    "use strict";

    jsPlumb.ready(function () {

        jsPlumb.setContainer("container");
        jsPlumb.importDefaults({
            ConnectionsDetachable: false
        });

        function exportAsImage() {
            alert("export");
        }

        function addRectangle() {
            alert("add rect");
        }

        function addCircle() {
            alert("add circle");
        }

        function initRectangles() {
            var rectLeftId = "rectLeft";
            var rectRightId = "rectRight";
            var commonConnectStyle = {
                anchors: ["Right", "Left"],
                type: "Straight"

            };

            jsPlumb.draggable([rectLeftId, rectRightId], {
                containment: true
            });

            jsPlumb.connect({
                source: rectLeftId,
                target: rectRightId,
                deleteEndpointsOnDetach: false,
                connector: ["Straight"],
                endpointStyle: {fill: "black"},
                endpoints: ["Blank", "Blank"],
                paintStyle: {stroke: "black", strokeWidth: 1}

            }, commonConnectStyle);

        }

        function initCircles() {
            var circleLeftId = "circleLeft";
            var circleRightId = "circleRight";
            var commonConnectStyle = {
                anchors: ["Right", "Left"]
            };

            jsPlumb.draggable([circleLeftId, circleRightId], {
                containment: true
            });

            jsPlumb.connect({
                source: circleLeftId,
                target: circleRightId,
                deleteEndpointsOnDetach: false,
                connector: ["Straight"],
                endpoints: ["Blank", "Blank"],
                paintStyle: {stroke: "black", strokeWidth: 1, dashstyle: "4 2"}
            }, commonConnectStyle);
        }

        function main() {
            initRectangles();
            initCircles();
            $("#addRectBtn").click(addRectangle);
            $("#addCircleBtn").click(addCircle);
            $("#exportBtn").click(exportAsImage);
        }

        main();
    });

})();
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';

export class DiaryComponent extends Component {

  static propTypes = {
    content: PropTypes.string
  };

  render() {
    const {content} = this.props;

    return (

YEAR MONTH DAY

    );
  }

}
<commit_msg>chore(diary.component.js): add header<commit_after>import React, {Component, PropTypes} from 'react';

export class DiaryComponent extends Component {

  static propTypes = {
    content: PropTypes.string
  };

  render() {
    const {content} = this.props;

    return (

Diary

    );
  }

}
<|endoftext|>


<commit_before>import './@FilterOptions.css'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Select from 'react-select'
import { Button, Panel } from 'react-bootstrap'
import FilterDateTime from './FilterDateTime'
import FilterCategory from './FilterCategory'
import FilterNumeric from './FilterNumeric'
import FilterBoolean from './FilterBoolean'

class FilterOptions extends Component {
  constructor (props) {
    super(props)

    this.renderFilterList = this.renderFilterList.bind(this)
  }

  renderFilterList () {
    let { filters, columns, handleRemoveFilter, applyFilter, updateFilter, dateBy } = this.props
    let filterOptions = Object.keys(filters).map((key) => {
      let filterContent = null
      let filterType
      let filter
      let checkboxOptions = {}
      if (key !== 'booleans') {
        filter = columns[key]
        filterType = (filter.type === 'text') && filter.categories ? 'category' : filter.type
      } else {
        filter = {key: 'booleans', name: 'True/False fields'}
        filterType = 'boolean'
        checkboxOptions = Object.keys(columns).filter((option) => {
          return columns[option].type === 'boolean'
        }).map((option) => {
          return {value: columns[option].key, label: columns[option].name}
        })
      }

      switch (filterType) {
        case 'date':
          let startDate = filters[key].options ? filters[key].options.min : filter.min
          let endDate = filters[key].options ? filters[key].options.max : filter.max
          filterContent = <FilterDateTime
            key={filter.key}
            fieldKey={filter.key}
            startDate={startDate}
            endDate={endDate}
            applyFilter={applyFilter}
            dateBy={dateBy} />
          break
        case 'category':
          let optionsForFilter = filter.categories.map(function (record) {
            if (!record.category) {
              return { label: 'Blank', value: 'blank' }
            }
            return { label: record.category, value: record.category }
          })
          filterContent = <FilterCategory
            key={filter.key}
            fieldKey={filter.key}
            options={optionsForFilter}
            applyFilter={applyFilter}
            filter={filters[key]} />
          break
        case 'boolean':
          filterContent = <FilterBoolean
            key={filter.key}
            fieldKey={filter.key}
            options={checkboxOptions}
            applyFilter={applyFilter}
            filter={filters[key]} />
          break
        case 'number':
          let nextRange = filters[key].options ? filters[key].options.nextRange : [parseInt(filter.min, 10), parseInt(filter.max, 10)]
          let currentRange = filters[key].options ? (filters[key].options.currentRange ? filters[key].options.currentRange : [parseInt(filter.min, 10), parseInt(filter.max, 10)]) : [parseInt(filter.min, 10), parseInt(filter.max, 10)]
          filterContent = <FilterNumeric
            key={filter.key}
            fieldKey={filter.key}
            min={parseInt(filter.min, 10)}
            max={parseInt(filter.max, 10)}
            currentRange={currentRange}
            nextRange={nextRange}
            filter={filters[key]}
            applyFilter={applyFilter}
            updateFilter={updateFilter}
            format={filter.format} />
          break
        default:
          return null
      }

      let filterOption = (

            <Button className='close' onClick={handleRemoveFilter.bind(this, filter.key)}>
              ×
            </Button>

{filter.name}

            {filterContent}

)

      return filterOption
    })
    return filterOptions
  }

  render () {
    let { handleAddFilter, options, filters } = this.props
    let booleans = false
    options = options.filter(field => {
      if (field.type === 'boolean') {
        booleans = true
        return false
      }
      return true
    })

    if (booleans) {
      options.push({value: 'booleans', label: 'True/False fields'})
    }

    return (
      <Panel className={'FilterChartOptions__root'} collapsible defaultExpanded header={
Selected field
} bsStyle={'primary'}>
        <Select
          className={'FilterChartOptions__select'}
          name='filters'
          placeholder='Add fields to filter by'
          options={options}
          onChange={handleAddFilter} />
        {filters ? this.renderFilterList() : false}
      </Panel>
    )
  }
}

FilterOptions.propTypes = {
  filters: PropTypes.object,
  columns: PropTypes.object,
  handleRemoveFilter: PropTypes.func,
  applyFilter: PropTypes.func,
  updateFilter: PropTypes.func,
  handleAddFilter: PropTypes.func
}

export default FilterOptions
<commit_msg>fix filter panel title<commit_after>import './@FilterOptions.css'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Select from 'react-select'
import { Button, Panel } from 'react-bootstrap'
import FilterDateTime from './FilterDateTime'
import FilterCategory from './FilterCategory'
import FilterNumeric from './FilterNumeric'
import FilterBoolean from './FilterBoolean'

class FilterOptions extends Component {
  constructor (props) {
    super(props)

    this.renderFilterList = this.renderFilterList.bind(this)
  }

  renderFilterList () {
    let { filters, columns, handleRemoveFilter, applyFilter, updateFilter, dateBy } = this.props
    let filterOptions = Object.keys(filters).map((key) => {
      let filterContent = null
      let filterType
      let filter
      let checkboxOptions = {}
      if (key !== 'booleans') {
        filter = columns[key]
        filterType = (filter.type === 'text') && filter.categories ? 'category' : filter.type
      } else {
        filter = {key: 'booleans', name: 'True/False fields'}
        filterType = 'boolean'
        checkboxOptions = Object.keys(columns).filter((option) => {
          return columns[option].type === 'boolean'
        }).map((option) => {
          return {value: columns[option].key, label: columns[option].name}
        })
      }

      switch (filterType) {
        case 'date':
          let startDate = filters[key].options ? filters[key].options.min : filter.min
          let endDate = filters[key].options ? filters[key].options.max : filter.max
          filterContent = <FilterDateTime
            key={filter.key}
            fieldKey={filter.key}
            startDate={startDate}
            endDate={endDate}
            applyFilter={applyFilter}
            dateBy={dateBy} />
          break
        case 'category':
          let optionsForFilter = filter.categories.map(function (record) {
            if (!record.category) {
              return { label: 'Blank', value: 'blank' }
            }
            return { label: record.category, value: record.category }
          })
          filterContent = <FilterCategory
            key={filter.key}
            fieldKey={filter.key}
            options={optionsForFilter}
            applyFilter={applyFilter}
            filter={filters[key]} />
          break
        case 'boolean':
          filterContent = <FilterBoolean
            key={filter.key}
            fieldKey={filter.key}
            options={checkboxOptions}
            applyFilter={applyFilter}
            filter={filters[key]} />
          break
        case 'number':
          let nextRange = filters[key].options ? filters[key].options.nextRange : [parseInt(filter.min, 10), parseInt(filter.max, 10)]
          let currentRange = filters[key].options ? (filters[key].options.currentRange ? filters[key].options.currentRange : [parseInt(filter.min, 10), parseInt(filter.max, 10)]) : [parseInt(filter.min, 10), parseInt(filter.max, 10)]
          filterContent = <FilterNumeric
            key={filter.key}
            fieldKey={filter.key}
            min={parseInt(filter.min, 10)}
            max={parseInt(filter.max, 10)}
            currentRange={currentRange}
            nextRange={nextRange}
            filter={filters[key]}
            applyFilter={applyFilter}
            updateFilter={updateFilter}
            format={filter.format} />
          break
        default:
          return null
      }

      let filterOption = (

            <Button className='close' onClick={handleRemoveFilter.bind(this, filter.key)}>
              ×
            </Button>

{filter.name}

            {filterContent}

)

      return filterOption
    })
    return filterOptions
  }

  render () {
    let { handleAddFilter, options, filters } = this.props
    let booleans = false
    options = options.filter(field => {
      if (field.type === 'boolean') {
        booleans = true
        return false
      }
      return true
    })

    if (booleans) {
      options.push({value: 'booleans', label: 'True/False fields'})
    }

    return (
      <Panel className={'FilterChartOptions__root'} collapsible defaultExpanded header={
Filter by other fields
} bsStyle={'primary'}>
        <Select
          className={'FilterChartOptions__select'}
          name='filters'
          placeholder='Add fields to filter by'
          options={options}
          onChange={handleAddFilter} />
        {filters ? this.renderFilterList() : false}
      </Panel>
    )
  }
}

FilterOptions.propTypes = {
  filters: PropTypes.object,
  columns: PropTypes.object,
  handleRemoveFilter: PropTypes.func,
  applyFilter: PropTypes.func,
  updateFilter: PropTypes.func,
  handleAddFilter: PropTypes.func
}

export default FilterOptions
<|endoftext|>


<commit_before>const moment           = require('moment');
const DatePicker       = require('../../components/date_picker');
const dateValueChanged = require('../../../_common/common_functions').dateValueChanged;
const toISOFormat      = require('../../../_common/string_util').toISOFormat;

const generateBirthDate = (min_age) => {
    const date_of_birth = '#date_of_birth';

    if (!$(date_of_birth).val()) {
        DatePicker.init({
            selector : date_of_birth,
            minDate  : -100 * 365,
            maxDate  : (-min_age * 365) - Math.trunc(min_age/4) - 1,
            yearRange: '-100:-18',
        });
        $(date_of_birth)
            .attr('data-value', toISOFormat(moment()))
            .change(function () {
                return dateValueChanged(this, 'date');
            })
            .val('');
    }
};

module.exports = generateBirthDate;
<commit_msg>add space<commit_after>const moment           = require('moment');
const DatePicker       = require('../../components/date_picker');
const dateValueChanged = require('../../../_common/common_functions').dateValueChanged;
const toISOFormat      = require('../../../_common/string_util').toISOFormat;

const generateBirthDate = (min_age) => {
    const date_of_birth = '#date_of_birth';

    if (!$(date_of_birth).val()) {
        DatePicker.init({
            selector : date_of_birth,
            minDate  : -100 * 365,
            maxDate  : (-min_age * 365) - Math.trunc(min_age / 4) - 1,
            yearRange: '-100:-18',
        });
        $(date_of_birth)
            .attr('data-value', toISOFormat(moment()))
            .change(function () {
                return dateValueChanged(this, 'date');
            })
            .val('');
    }
};

module.exports = generateBirthDate;
<|endoftext|>


<commit_before><commit_msg>Fix scope issue<commit_after><|endoftext|>


<commit_before>addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;

function sortables_init() {
		var lastAssignedId = 0;
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
				if (!thisTbl.id) {
      		thisTbl.id = 'sortableTable'+this.lastAssignedId++;
    		}
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            //initTable(thisTbl.id);
            ts_makeSortable(thisTbl);
        }
    }
}

function ts_makeSortable(table) {
    if (table.rows && table.rows.length > 0) {
        var firstRow = table.rows[0];
    }
    if (!firstRow) return;

    // We have a first row: assume it's the header, and make its contents clickable links
    for (var i=0;i<firstRow.cells.length;i++) {
        var cell = firstRow.cells[i];
        var txt = ts_getInnerText(cell);
        cell.innerHTML = '' +
        txt+'   ';
    }
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";

	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk,clid) {
    // get the span
    var span;
    for (var ci=0;ci<lnk.childNodes.length;ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    while(td.nodeName.toLowerCase() != 'td')
        td = td.parentNode;
    var column = clid || td.cellIndex;
    var table = getParent(td,'TABLE');

    // Work out a type for the column
    if (table.rows.length <= 1) return;
    var itm = ts_getInnerText(table.rows[1].cells[column]);
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^[$]/)) sortfn = ts_sort_currency;
    if (itm.match(/^[\d\.]+\s*(bytes|b|kb|tb|gb|mb)$/i)) sortfn = ts_sort_filesize;
    // Special cases for our mailbox lists
    if (itm.match(/^(Empty|Unlimited)$/)) sortfn = ts_sort_filesize;
    if (itm.match(/^[\d\.]+%?$/)) sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
    for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }

    newRows.sort(sortfn);

    if (span.getAttribute("sortdir") == 'down') {
        ARROW = '  ↑';
        newRows.reverse();
        span.setAttribute('sortdir','up');
    } else {
        ARROW = '  ↓';
        span.setAttribute('sortdir','down');
    }

    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
    // do sortbottom rows only
    for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}

    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci=0;ci<allspans.length;ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
                allspans[ci].innerHTML = '   ';
            }
        }
    }

    span.innerHTML = ARROW;
}

function getParent(el, pTagName) {
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
		return el;
	else
		return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
    } else {
        yr = aa.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
    } else {
        yr = bb.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
    }
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_currency(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    return parseFloat(aa) - parseFloat(bb);
}

// handles file sizes, simple numerics, and Unlimited/Empty/None special cases
function ts_sort_filesize(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();

    if (aa.length == 0) return -1;
    else if (bb.length == 0) return 1;

    var regex = /^([\d\.]*|none|empty|unlimited)\s*(bytes|b|kb|tb|gb|mb)?$/i;
    matchA = aa.match(regex);
    matchB = bb.match(regex);

    // Give file size class an integer value, if we don't already have one
    if (matchA[1] == 'none') valA = -999;
    else if (matchA[1] == 'empty') valA = 0;
    else if (matchA[1] == '0') valA = 0;
    else if (matchA[1] == 'unlimited') valA = 999;
    else if (matchA[2] == 'b' || matchA[2] == 'bytes') valA = 1;
    else if (matchA[2] == undefined || matchA[2] == '') valA = 1;
    else if (matchA[2] == 'kb') valA = 2;
    else if (matchA[2] == 'mb') valA = 3;
    else if (matchA[2] == 'gb') valA = 4;
    else if (matchA[2] == 'tb') valA = 5;

    if (matchB[1] == 'none') valB = -999;
    else if (matchB[1] == 'empty') valB = 0;
    else if (matchB[1] == '0') valB = 0;
    else if (matchB[1] == 'unlimited') valB = 999;
    else if (matchB[2] == 'b' || matchB[2] == 'bytes') valB = 1;
    else if (matchB[2] == undefined || matchB[2] == '') valB = 1;
    else if (matchB[2] == 'kb') valB = 2;
    else if (matchB[2] == 'mb') valB = 3;
    else if (matchB[2] == 'gb') valB = 4;
    else if (matchB[2] == 'tb') valB = 5;

    if (valA == valB) {
			if ( isNaN(matchA[1])) return -1;
      if ( isNaN(matchB[1])) return 1;
      // Files are in the same size class kb/gb/mb/etc
      // just do a numeric sort on the file size
			return matchA[1]-matchB[1];
    } else if (valA < valB) {
      return -1;
    } else if (valA > valB) {
      return 1;
    }
}

function ts_sort_numeric(a,b) {
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
    if (isNaN(bb)) bb = 0;
    return aa-bb;
}

function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
}
<commit_msg>Fix sorting by date https://www.virtualmin.com/node/18406<commit_after>addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;

function sortables_init() {
		var lastAssignedId = 0;
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
				if (!thisTbl.id) {
      		thisTbl.id = 'sortableTable'+this.lastAssignedId++;
    		}
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            //initTable(thisTbl.id);
            ts_makeSortable(thisTbl);
        }
    }
}

function ts_makeSortable(table) {
    if (table.rows && table.rows.length > 0) {
        var firstRow = table.rows[0];
    }
    if (!firstRow) return;

    // We have a first row: assume it's the header, and make its contents clickable links
    for (var i=0;i<firstRow.cells.length;i++) {
        var cell = firstRow.cells[i];
        var txt = ts_getInnerText(cell);
        cell.innerHTML = '' +
        txt+'   ';
    }
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";

	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk,clid) {
    // get the span
    var span;
    for (var ci=0;ci<lnk.childNodes.length;ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    while(td.nodeName.toLowerCase() != 'td')
        td = td.parentNode;
    var column = typeof(clid) == 'undefined' ? td.cellIndex : clid;
    var table = getParent(td,'TABLE');

    // Work out a type for the column
    if (table.rows.length <= 1) return;
    var itm = ts_getInnerText(table.rows[1].cells[column]);
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\S\S\S[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^[$]/)) sortfn = ts_sort_currency;
    if (itm.match(/^[\d\.]+\s*(bytes|b|kb|tb|gb|mb)$/i)) sortfn = ts_sort_filesize;
    // Special cases for our mailbox lists
    if (itm.match(/^(Empty|Unlimited)$/)) sortfn = ts_sort_filesize;
    if (itm.match(/^[\d\.]+%?$/)) sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
    for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }

    newRows.sort(sortfn);

    if (span.getAttribute("sortdir") == 'down') {
        ARROW = '  ↑';
        newRows.reverse();
        span.setAttribute('sortdir','up');
    } else {
        ARROW = '  ↓';
        span.setAttribute('sortdir','down');
    }

    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
    // do sortbottom rows only
    for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}

    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci=0;ci<allspans.length;ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
                allspans[ci].innerHTML = '   ';
            }
        }
    }

    span.innerHTML = ARROW;
}

function getParent(el, pTagName) {
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
		return el;
	else
		return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        // yyyy/mm/dd format
        dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
    } else if (aa.length == 11) {
        // dd/mon/yyyy format
        dt1 = aa.substr(7,4)+ts_month_num(aa.substr(3,3))+aa.substr(0,2);
    } else {
        yr = aa.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
    } else if (bb.length == 11) {
        // dd/mon/yyyy format
        dt2 = bb.substr(7,4)+ts_month_num(bb.substr(3,3))+bb.substr(0,2);
    } else {
        yr = bb.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
    }
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_month_num(month) {
  month = month.toLowerCase();
  return month == 'jan' ? '01' :
	 month == 'feb' ? '02' :
	 month == 'mar' ? '03' :
	 month == 'apr' ? '04' :
	 month == 'may' ? '05' :
	 month == 'jun' ? '06' :
	 month == 'jul' ? '07' :
	 month == 'aug' ? '08' :
	 month == 'sep' ? '09' :
	 month == 'oct' ? '10' :
	 month == 'nov' ? '11' :
	 month == 'dec' ? '12' : '00';
}

function ts_sort_currency(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    return parseFloat(aa) - parseFloat(bb);
}

// handles file sizes, simple numerics, and Unlimited/Empty/None special cases
function ts_sort_filesize(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();

    if (aa.length == 0) return -1;
    else if (bb.length == 0) return 1;

    var regex = /^([\d\.]*|none|empty|unlimited)\s*(bytes|b|kb|tb|gb|mb)?$/i;
    matchA = aa.match(regex);
    matchB = bb.match(regex);

    // Give file size class an integer value, if we don't already have one
    if (matchA[1] == 'none') valA = -999;
    else if (matchA[1] == 'empty') valA = 0;
    else if (matchA[1] == '0') valA = 0;
    else if (matchA[1] == 'unlimited') valA = 999;
    else if (matchA[2] == 'b' || matchA[2] == 'bytes') valA = 1;
    else if (matchA[2] == undefined || matchA[2] == '') valA = 1;
    else if (matchA[2] == 'kb') valA = 2;
    else if (matchA[2] == 'mb') valA = 3;
    else if (matchA[2] == 'gb') valA = 4;
    else if (matchA[2] == 'tb') valA = 5;

    if (matchB[1] == 'none') valB = -999;
    else if (matchB[1] == 'empty') valB = 0;
    else if (matchB[1] == '0') valB = 0;
    else if (matchB[1] == 'unlimited') valB = 999;
    else if (matchB[2] == 'b' || matchB[2] == 'bytes') valB = 1;
    else if (matchB[2] == undefined || matchB[2] == '') valB = 1;
    else if (matchB[2] == 'kb') valB = 2;
    else if (matchB[2] == 'mb') valB = 3;
    else if (matchB[2] == 'gb') valB = 4;
    else if (matchB[2] == 'tb') valB = 5;

    if (valA == valB) {
			if ( isNaN(matchA[1])) return -1;
      if ( isNaN(matchB[1])) return 1;
      // Files are in the same size class kb/gb/mb/etc
      // just do a numeric sort on the file size
			return matchA[1]-matchB[1];
    } else if (valA < valB) {
      return -1;
    } else if (valA > valB) {
      return 1;
    }
}

function ts_sort_numeric(a,b) {
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
    if (isNaN(bb)) bb = 0;
    return aa-bb;
}

function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
}
<|endoftext|>


<commit_before>var Collider = require('../src/collider').Collider;
var Maths = Collider.Maths;

var mockObj = function(posX, posY, sizeX, sizeY, boundingBox) {
  return {
    pos: { x:posX, y:posY },
    size: { x:sizeX, y:sizeY },
    boundingBox: boundingBox
  };
};

describe('collider', function() {
  describe('maths', function() {
    describe('rectangleCorners', function() {
      it('should get corners of rect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var corners = Maths.rectangleCorners(obj);
        expect(corners[0]).toEqual({ x:5, y:5 });
        expect(corners[1]).toEqual({ x:15, y:5 });
        expect(corners[2]).toEqual({ x:15, y:15 });
        expect(corners[3]).toEqual({ x:5, y:15 });
      });
    });

    describe('isLineIntersectingCircle', function() {
      it('should return false when circle and line intersect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var intersecting = Maths.isLineIntersectingCircle(obj, { x:1, y:1 }, { x:20, y:20 });
        expect(intersecting).toEqual(true);
      });

      it('should return false when circle and line do not intersect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var intersecting = Maths.isLineIntersectingCircle(obj, { x:1, y:1 }, { x:1, y:20 });
        expect(intersecting).toEqual(false);
      });
    });

    describe('circleAndRectangleIntersecting', function() {
      it('should return true when centres align', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(7, 7, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(true);
      });

      it('should return true when circle and rect overlap a bit', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(7, 7, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(true);
      });

      it('should return false when circle and rect do not intersect', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(16, 16, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(false);
      });
    });

    describe('isIntersecting', function() {
      it('should use rect as default bounding box', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10);
        var obj2 = mockObj(15, 15, 10, 10);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return true for two rects that are colliding', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10);
        var obj2 = mockObj(15, 15, 10, 10);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return false for two circles that are not colliding', function() {
        var obj1 = mockObj(5, 5, 10, 10, Coquette.get().collider.CIRCLE);
        var obj2 = mockObj(14, 14, 10, 10, Coquette.get().collider.CIRCLE);
        var collider = new Collider();
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(false);
      });

      it('should return true for circle+rect that are colliding (circle first)', function() {
        var obj1 = mockObj(5, 5, 10, 10, Coquette.get().collider.CIRCLE);
        var obj2 = mockObj(12, 12, 10, 10, Coquette.get().collider.RECTANGLE);
        var collider = new Collider();
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return true for circle+rect that are colliding (rect first)', function() {
        var obj1 = mockObj(5, 5, 10, 10, Coquette.get().collider.RECTANGLE);
        var obj2 = mockObj(12, 12, 10, 10, Coquette.get().collider.CIRCLE);
        var collider = new Collider();
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });
    });
  });
});
<commit_msg>Make references to RECTANGLE and CIRCLE constants work.<commit_after>var Collider = require('../src/collider').Collider;
var Maths = Collider.Maths;

var mockObj = function(posX, posY, sizeX, sizeY, boundingBox) {
  return {
    pos: { x:posX, y:posY },
    size: { x:sizeX, y:sizeY },
    boundingBox: boundingBox
  };
};

describe('collider', function() {
  describe('maths', function() {
    describe('rectangleCorners', function() {
      it('should get corners of rect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var corners = Maths.rectangleCorners(obj);
        expect(corners[0]).toEqual({ x:5, y:5 });
        expect(corners[1]).toEqual({ x:15, y:5 });
        expect(corners[2]).toEqual({ x:15, y:15 });
        expect(corners[3]).toEqual({ x:5, y:15 });
      });
    });

    describe('isLineIntersectingCircle', function() {
      it('should return false when circle and line intersect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var intersecting = Maths.isLineIntersectingCircle(obj, { x:1, y:1 }, { x:20, y:20 });
        expect(intersecting).toEqual(true);
      });

      it('should return false when circle and line do not intersect', function() {
        var obj = mockObj(5, 5, 10, 10);
        var intersecting = Maths.isLineIntersectingCircle(obj, { x:1, y:1 }, { x:1, y:20 });
        expect(intersecting).toEqual(false);
      });
    });

    describe('circleAndRectangleIntersecting', function() {
      it('should return true when centres align', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(7, 7, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(true);
      });

      it('should return true when circle and rect overlap a bit', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(7, 7, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(true);
      });

      it('should return false when circle and rect do not intersect', function() {
        var circle = mockObj(5, 5, 10, 10);
        var rectangle = mockObj(16, 16, 10, 10);
        var intersecting = Maths.circleAndRectangleIntersecting(circle, rectangle);
        expect(intersecting).toEqual(false);
      });
    });

    describe('isIntersecting', function() {
      it('should use rect as default bounding box', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10);
        var obj2 = mockObj(15, 15, 10, 10);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return true for two rects that are colliding', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10);
        var obj2 = mockObj(15, 15, 10, 10);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return false for two circles that are not colliding', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10, collider.CIRCLE);
        var obj2 = mockObj(14, 14, 10, 10, collider.CIRCLE);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(false);
      });

      it('should return true for circle+rect that are colliding (circle first)', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10, collider.CIRCLE);
        var obj2 = mockObj(12, 12, 10, 10, collider.RECTANGLE);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });

      it('should return true for circle+rect that are colliding (rect first)', function() {
        var collider = new Collider();
        var obj1 = mockObj(5, 5, 10, 10, collider.RECTANGLE);
        var obj2 = mockObj(12, 12, 10, 10, collider.CIRCLE);
        var intersecting = collider.isIntersecting(obj1, obj2);
        expect(intersecting).toEqual(true);
      });
    });
  });
});
<|endoftext|>


<commit_before>var RSVP  = require('rsvp');
var chalk = require('chalk');

module.exports = {
  description: 'install ember-material-lite into a typical project',

  beforeInstall: function (options) {
    return RSVP.all([
      this.addBowerPackageToProject('material-design-lite', '~1.0.3')
    ]);
  },

  afterInstall: function () {
    return RSVP.all([
      this.addPackageToProject('ember-cli-sass', '^3.3.0'),
      this.addPackageToProject('ember-new-computed', '~1.0.0'),
      this.addPackageToProject('ember-legacy-views', '~0.2.0'),
      this.addPackageToProject('ember-truth-helpers', '~1.1.0'),
      this.addPackageToProject('ember-composability', '~0.2.0'),
    ]);
  }
};
<commit_msg>fixes #29 added normalizeEntityName override to prevent error during install<commit_after>var RSVP  = require('rsvp');
var chalk = require('chalk');

module.exports = {
  description: 'install ember-material-lite into a typical project',
  normalizeEntityName: function() {}, // no-op since we're just adding dependencies

  beforeInstall: function (options) {
    return RSVP.all([
      this.addBowerPackageToProject('material-design-lite', '~1.0.3')
    ]);
  },

  afterInstall: function () {
    return RSVP.all([
      this.addPackageToProject('ember-cli-sass', '^3.3.0'),
      this.addPackageToProject('ember-new-computed', '~1.0.0'),
      this.addPackageToProject('ember-legacy-views', '~0.2.0'),
      this.addPackageToProject('ember-truth-helpers', '~1.1.0'),
      this.addPackageToProject('ember-composability', '~0.2.0'),
    ]);
  }
};
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
 */

'use strict';

/**
 * Helper `gen` function calls node type handler.
 */
function gen(node) {
  return node ? generator[node.type](node) : '';
}

/**
 * AST handler.
 */
const generator = {
  RegExp(node) {
    return `/${gen(node.body)}/${node.flags}`;
  },

  Alternative(node) {
    return (node.expressions || [])
      .map(node => gen(node))
      .join('');
  },

  Disjunction(node) {
    return `${gen(node.left)}|${gen(node.right)}`;
  },

  Group(node) {
    const expression = gen(node.expression);

    if (node.capturing) {
      return `(${expression})`;
    }

    return `(?:${expression})`;
  },

  Assertion(node) {
    switch (node.kind) {
      case '^': return '^';
      case '$': return '$';
      case '\\b': return '\\b';
      case '\\B': return '\\B';

      case 'Lookahead': {
        const assertion = gen(node.assertion);

        if (node.negative) {
          return `(?!${assertion})`;
        }

        return `(?=${assertion})`;
      }

      default:
        throw new TypeError('Unknown Assertion kind: ' + node.kind);
    }
  },

  CharacterClass(node) {
    const expressions = (node.expressions || [])
      .map(node => gen(node))
      .join('');

    if (node.negative) {
      return `[^${expressions}]`;
    }

    return `[${expressions}]`;
  },

  ClassRange(node) {
    return `${gen(node.from)}-${gen(node.to)}`;
  },

  Repetition(node) {
    return `${gen(node.expression)}${gen(node.quantifier)}`;
  },

  Quantifier(node) {
    let quantifier;
    const greedy = node.greedy ? '' : '?';

    switch (node.kind) {
      case '+':
        quantifier = `+`;
        break;
      case '?':
        quantifier = `?`;
        break;
      case '*':
        quantifier = `*`;
        break;
      case 'Range':
        // Exact: {1}
        if (node.from === node.to) {
          quantifier = `{${node.from}}`;
        }
        // Open: {1,}
        else if (!node.to) {
          quantifier = `{${node.from},}`;
        }
        // Closed: {1,3}
        else {
          quantifier = `{${node.from},${node.to}}`;
        }
        break;
      default:
        throw new TypeError('Unknown Quantifier kind: ' + node.kind);
    }

    return `${quantifier}${greedy}`;
  },

  Char(node) {
    const value = node.value;

    switch (node.kind) {
      case 'simple': {
        if (node.escaped) {
          return `\\${value}`;
        }
        return value;
      }

      case 'hex':
      case 'unicode':
      case 'oct':
      case 'decimal':
      case 'control':
      case 'meta':
        return value;

      default:
        throw new TypeError('Unknown Char kind: ' + node.kind);
    }
  },
};

module.exports = {
  /**
   * Generates a regexp string from an AST.
   *
   * @param Object ast - an AST node
   */
  generate: gen,
};<commit_msg>more template strings<commit_after>/**
 * The MIT License (MIT)
 * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
 */

'use strict';

/**
 * Helper `gen` function calls node type handler.
 */
function gen(node) {
  return node ? generator[node.type](node) : '';
}

/**
 * AST handler.
 */
const generator = {
  RegExp(node) {
    return `/${gen(node.body)}/${node.flags}`;
  },

  Alternative(node) {
    return (node.expressions || [])
      .map(node => gen(node))
      .join('');
  },

  Disjunction(node) {
    return `${gen(node.left)}|${gen(node.right)}`;
  },

  Group(node) {
    const expression = gen(node.expression);

    if (node.capturing) {
      return `(${expression})`;
    }

    return `(?:${expression})`;
  },

  Assertion(node) {
    switch (node.kind) {
      case '^': return '^';
      case '$': return '$';
      case '\\b': return '\\b';
      case '\\B': return '\\B';

      case 'Lookahead': {
        const assertion = gen(node.assertion);

        if (node.negative) {
          return `(?!${assertion})`;
        }

        return `(?=${assertion})`;
      }

      default:
        throw new TypeError(`Unknown Assertion kind: ${node.kind}`);
    }
  },

  CharacterClass(node) {
    const expressions = (node.expressions || [])
      .map(node => gen(node))
      .join('');

    if (node.negative) {
      return `[^${expressions}]`;
    }

    return `[${expressions}]`;
  },

  ClassRange(node) {
    return `${gen(node.from)}-${gen(node.to)}`;
  },

  Repetition(node) {
    return `${gen(node.expression)}${gen(node.quantifier)}`;
  },

  Quantifier(node) {
    let quantifier;
    const greedy = node.greedy ? '' : '?';

    switch (node.kind) {
      case '+':
        quantifier = `+`;
        break;
      case '?':
        quantifier = `?`;
        break;
      case '*':
        quantifier = `*`;
        break;
      case 'Range':
        // Exact: {1}
        if (node.from === node.to) {
          quantifier = `{${node.from}}`;
        }
        // Open: {1,}
        else if (!node.to) {
          quantifier = `{${node.from},}`;
        }
        // Closed: {1,3}
        else {
          quantifier = `{${node.from},${node.to}}`;
        }
        break;
      default:
        throw new TypeError(`Unknown Quantifier kind: ${node.kind}`);
    }

    return `${quantifier}${greedy}`;
  },

  Char(node) {
    const value = node.value;

    switch (node.kind) {
      case 'simple': {
        if (node.escaped) {
          return `\\${value}`;
        }
        return value;
      }

      case 'hex':
      case 'unicode':
      case 'oct':
      case 'decimal':
      case 'control':
      case 'meta':
        return value;

      default:
        throw new TypeError(`Unknown Char kind: ${node.kind}`);
    }
  },
};

module.exports = {
  /**
   * Generates a regexp string from an AST.
   *
   * @param Object ast - an AST node
   */
  generate: gen,
};<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import $ from "jquery";
import Backbone from 'backbone';
import Router from 'react-router';

export default React.createClass({
    displayName: "Tag",

    propTypes: {
      tag: React.PropTypes.instanceOf(Backbone.Model).isRequired,
      renderLinks: React.PropTypes.bool
    },

    getDefaultProps: function () {
      return {
        renderLinks: true
      }
    },

    componentDidMount: function () {
      var el = ReactDOM.findDOMNode(this),
        $el = $(el),
        tag = this.props.tag;

      $el.tooltip({
        title: tag.get('description'),
        placement: 'left'
      });
    },

    onClick: function () {
      Router.getInstance().transitionTo("search", {}, {q: this.props.tag.get('name')});
    },

    render: function () {
      var tag = this.props.tag,
        tagName = tag.get('name'),
        link;

      if (this.props.renderLinks) {
        link = (
          <Router.Link to="search" query={{q: tagName}}>
            {tagName}
          </Router.Link>
        );
      } else {
        link = (
          {tagName}
        )
      }

      return (

          {link}

      );

    }
});
<commit_msg>Remove unused click handler<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import $ from "jquery";
import Backbone from 'backbone';
import Router from 'react-router';

export default React.createClass({
    displayName: "Tag",

    propTypes: {
      tag: React.PropTypes.instanceOf(Backbone.Model).isRequired,
      renderLinks: React.PropTypes.bool
    },

    getDefaultProps: function () {
      return {
        renderLinks: true
      }
    },

    componentDidMount: function () {
      var el = ReactDOM.findDOMNode(this),
        $el = $(el),
        tag = this.props.tag;

      $el.tooltip({
        title: tag.get('description'),
        placement: 'left'
      });
    },

    render: function () {
      var tag = this.props.tag,
        tagName = tag.get('name'),
        link;

      if (this.props.renderLinks) {
        link = (
          <Router.Link to="search" query={{q: tagName}}>
            {tagName}
          </Router.Link>
        );
      } else {
        link = (
          {tagName}
        )
      }

      return (

          {link}

      );

    }
});
<|endoftext|>


<commit_before>// @flow
import loadImageElement from './loadImageElement';

export function convertImageDataToBlob(imageData: ImageData): Promise<Blob> {
  return new Promise(resolve => {
    const canvas = document.createElement('canvas');
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);
    canvas.toBlob(blob => resolve(blob));
  });
}

function convertImageDataToImageElement(
  imageData: ImageData
): Promise<HTMLImageElement> {
  return convertImageDataToBlob(imageData).then(blob => {
    const url = URL.createObjectURL(blob);
    return loadImageElement(url).then(image => {
      URL.revokeObjectURL(url);
      return image;
    });
  });
}

export function convertBlobToImageData(blob: Blob): Promise<ImageData> {
  const url = URL.createObjectURL(blob);
  return loadImageElement(url).then(image => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = image.width;
    canvas.height = image.height;
    ctx.drawImage(image, 0, 0);
    URL.revokeObjectURL(url);
    return ctx.getImageData(0, 0, image.width, image.height);
  });
}

export function synthesizeImageData(
  imageDatas: ImageData[],
  width: number,
  height: number
): Promise<ImageData> {
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext('2d');
  return Promise.all(
    imageDatas.map(i => convertImageDataToImageElement(i))
  ).then(images => {
    images.forEach(image => {
      ctx.drawImage(image, 0, 0, image.width, image.height);
    });
    return ctx.getImageData(0, 0, width, height);
  });
}
<commit_msg>resizeImageData を定義。<commit_after>// @flow
import loadImageElement from './loadImageElement';

export function convertImageDataToBlob(imageData: ImageData): Promise<Blob> {
  return new Promise(resolve => {
    const canvas = document.createElement('canvas');
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);
    canvas.toBlob(blob => resolve(blob));
  });
}

function convertImageDataToImageElement(
  imageData: ImageData
): Promise<HTMLImageElement> {
  return convertImageDataToBlob(imageData).then(blob => {
    const url = URL.createObjectURL(blob);
    return loadImageElement(url).then(image => {
      URL.revokeObjectURL(url);
      return image;
    });
  });
}

export function convertBlobToImageData(blob: Blob): Promise<ImageData> {
  const url = URL.createObjectURL(blob);
  return loadImageElement(url).then(image => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = image.width;
    canvas.height = image.height;
    ctx.drawImage(image, 0, 0);
    URL.revokeObjectURL(url);
    return ctx.getImageData(0, 0, image.width, image.height);
  });
}

export function synthesizeImageData(
  imageDatas: ImageData[],
  width: number,
  height: number
): Promise<ImageData> {
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext('2d');
  return Promise.all(
    imageDatas.map(i => convertImageDataToImageElement(i))
  ).then(images => {
    images.forEach(image => {
      ctx.drawImage(image, 0, 0, image.width, image.height);
    });
    return ctx.getImageData(0, 0, width, height);
  });
}

export function resizeImageData(
  src: ImageData,
  resizeRatioPercent: number
): ImageData {
  const srcCanvas = document.createElement('canvas');
  const srcCtx = srcCanvas.getContext('2d');
  srcCanvas.width = src.width;
  srcCanvas.height = src.height;
  srcCtx.putImageData(src, 0, 0);

  const destCanvas = document.createElement('canvas');
  const destCtx = srcCanvas.getContext('2d');
  destCanvas.width = Math.floor(src.width * (resizeRatioPercent / 100));
  destCanvas.height = Math.floor(src.height * (resizeRatioPercent / 100));
  const {width, height} = destCanvas;
  destCtx.drawImage(srcCanvas, 0, 0, width, height);
  return destCtx.getImageData(0, 0, width, height);
}
<|endoftext|>


<commit_before>const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OfflinePlugin = require('offline-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');

module.exports = require('./webpack.base.babel')({
  mode: 'production',
  // In production, we skip all hot-reloading stuff
  entry: [path.join(process.cwd(), 'app/index.js')],

  // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },

  optimization: {
    minimize: true,
    sideEffects: true,
    concatenateModules: true,
  },

  plugins: [
    // Minify and optimize the index.html
    new HtmlWebpackPlugin({
      template: 'app/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
      inject: true,
    }),

    new WebpackPwaManifest({
      name: 'KaniWani',
      short_name: 'KaniWani',
      description: 'English <-> Japanese Study Tool',
      background_color: '#fafafa',
      theme_color: '#8523e7',
      display: 'standalone',
      orientation: 'portrait',
      start_url: '/',
      icons: [
        {
          src: path.resolve('app/favicon.png'),
          sizes: [36, 48, 72, 96, 144, 192, 512],
        },
      ],
    }),

    // Put it in the end to capture all the HtmlWebpackPlugin's
    // assets manipulations and do leak its manipulations to HtmlWebpackPlugin
    new OfflinePlugin({
      relativePaths: false,
      publicPath: '/',

      ServiceWorker: {
        minify: false, // TODO: Can minify when offline-plugin supports webpack 4
        events: true,
      },

      // No need to cache .htaccess. See http://mxs.is/googmp,
      // this is applied before any match in `caches` section
      excludes: ['.htaccess'],

      caches: {
        main: [':rest:'],

        // All chunks marked as `additional`, loaded after main section
        // and do not prevent SW to install. Change to `optional` if
        // do not want them to be preloaded at all (cached only when first loaded)
        additional: ['*.chunk.js', '*.png', '*.svg', '*.jpg'],
      },

      // Removes warning for about `additional` section usage
      safeToUseOptionalCaches: true,

      autoUpdate: true,

      AppCache: false,
    }),
  ],

  performance: {
    assetFilter: (assetFilename) => !/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename),
  },
});
<commit_msg>fix: remove fingerprinting from manifest filename<commit_after>const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OfflinePlugin = require('offline-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');

module.exports = require('./webpack.base.babel')({
  mode: 'production',
  // In production, we skip all hot-reloading stuff
  entry: [path.join(process.cwd(), 'app/index.js')],

  // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },

  optimization: {
    minimize: true,
    sideEffects: true,
    concatenateModules: true,
  },

  plugins: [
    // Minify and optimize the index.html
    new HtmlWebpackPlugin({
      template: 'app/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
      inject: true,
    }),

    new WebpackPwaManifest({
      filename: 'manifest.json',
      name: 'KaniWani',
      short_name: 'KaniWani',
      background_color: '#fafafa',
      theme_color: '#8523e7',
      display: 'standalone',
      orientation: 'portrait',
      start_url: '/',
      icons: [
        {
          src: path.resolve('app/favicon.png'),
          sizes: [36, 48, 72, 96, 144, 192, 512],
        },
      ],
    }),

    // Put it in the end to capture all the HtmlWebpackPlugin's
    // assets manipulations and do leak its manipulations to HtmlWebpackPlugin
    new OfflinePlugin({
      relativePaths: false,
      publicPath: '/',

      ServiceWorker: {
        minify: false, // TODO: Can minify when offline-plugin supports webpack 4
        events: true,
      },

      // No need to cache .htaccess. See http://mxs.is/googmp,
      // this is applied before any match in `caches` section
      excludes: ['.htaccess'],

      caches: {
        main: [':rest:'],

        // All chunks marked as `additional`, loaded after main section
        // and do not prevent SW to install. Change to `optional` if
        // do not want them to be preloaded at all (cached only when first loaded)
        additional: ['*.chunk.js', '*.png', '*.svg', '*.jpg'],
      },

      // Removes warning for about `additional` section usage
      safeToUseOptionalCaches: true,

      autoUpdate: true,

      AppCache: false,
    }),
  ],

  performance: {
    assetFilter: (assetFilename) => !/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename),
  },
});
<|endoftext|>


<commit_before>var L = A.Lang,
	isBoolean = L.isBoolean,
	isFunction = L.isFunction,
	isString = L.isString,

	defaults = AUI.defaults.io,

	getDefault = function(attr) {
		return function() {
			return defaults[attr];
		};
	},

	ACTIVE = 'active',
	ARGUMENTS = 'arguments',
	AUTO_LOAD = 'autoLoad',
	CACHE = 'cache',
	CFG = 'cfg',
	COMPLETE = 'complete',
	CONTENT_TYPE = 'content-type',
	CONTEXT = 'context',
	DATA = 'data',
	DATA_TYPE = 'dataType',
	EMPTY_STRING = '',
	END = 'end',
	FAILURE = 'failure',
	FORM = 'form',
	GET = 'get',
	HEADERS = 'headers',
	IO_REQUEST = 'IORequest',
	JSON = 'json',
	METHOD = 'method',
	RESPONSE_DATA = 'responseData',
	START = 'start',
	SUCCESS = 'success',
	SYNC = 'sync',
	TIMEOUT = 'timeout',
	TRANSACTION = 'transaction',
	URI = 'uri',
	XDR = 'xdr',
	XML = 'xml',

	PARSE_ERROR = 'Parser error: IO dataType is not correctly parsing',

	ACCEPTS = {
		all: '*/*',
		html: 'text/html',
		json: 'application/json, text/javascript',
		text: 'text/plain',
		xml: 'application/xml, text/xml'
	};

function IORequest() {
	IORequest.superclass.constructor.apply(this, arguments);
}

A.mix(IORequest, {
	NAME: IO_REQUEST,

	ATTRS: {
		autoLoad: {
			value: true,
			validator: isBoolean
		},

		cache: {
			value: true,
			validator: isBoolean
		},

		dataType: {
			setter: function(v) {
				return (v || EMPTY_STRING).toLowerCase();
			},
			value: null,
			validator: isString
		},

		responseData: {
			setter: function(v) {
				return this._setResponseData(v);
			},
			value: null
		},

		uri: {
			setter: function(v) {
				return this._parseURL(v);
			},
			value: null,
			validator: isString
		},

		// User readOnly variables

		active: {
			value: false,
			validator: isBoolean
		},

		cfg: {
			getter: function() {
				var instance = this;

				// keep the current cfg object always synchronized with the mapped public attributes
				// when the user call .start() it always retrieve the last set values for each mapped attr
				return {
					arguments: instance.get(ARGUMENTS),
					context: instance.get(CONTEXT),
					data: instance.get(DATA),
					form: instance.get(FORM),
					headers: instance.get(HEADERS),
					method: instance.get(METHOD),
					on: {
						complete: A.bind(instance.fire, instance, COMPLETE),
						end: A.bind(instance._end, instance),
						failure: A.bind(instance.fire, instance, FAILURE),
						start: A.bind(instance.fire, instance, START),
						success: A.bind(instance._success, instance)
					},
					sync: instance.get(SYNC),
					timeout: instance.get(TIMEOUT),
					xdr: instance.get(XDR)
				}
			},
			readOnly: true
		},

		transaction: {
			value: null
		},

		// Configuration Object mapping
		// To take advantages of the Attribute listeners of A.Base
		// See: http://developer.yahoo.com/yui/3/io/

		arguments: {
			valueFn: getDefault(ARGUMENTS)
		},

		context: {
			valueFn: getDefault(CONTEXT)
		},

		data: {
			valueFn: getDefault(DATA)
		},

		form: {
			valueFn: getDefault(FORM)
		},

		// set the correct ACCEPT header based on the dataType
		headers: {
			getter: function(value) {
				var header = [];
				var instance = this;
				var dataType = instance.get(DATA_TYPE);

				if (dataType) {
					header.push(
						ACCEPTS[dataType]
					);
				}

				// always add *.* to the accept header
				header.push(
					ACCEPTS.all
				);

				return A.merge(
					value,
					{
						Accept: header.join(', ')
					}
				);
			},
			valueFn: getDefault(HEADERS)
		},

		method: {
			valueFn: getDefault(METHOD)
		},

		sync: {
			valueFn: getDefault(SYNC)
		},

		timeout: {
			valueFn: getDefault(TIMEOUT)
		},

		xdr: {
			valueFn: getDefault(XDR)
		}
	}
});

A.extend(IORequest, A.Plugin.Base, {
	/*
	* Lifecycle
	*/
	initializer: function(config) {
		var instance = this;

		instance.after('init', instance._afterInit);
	},

	_afterInit: function() {
		var instance = this;

		if (instance.get(AUTO_LOAD)) {
			instance.start();
		}
	},

	destructor: function() {
		var instance = this;

		instance.stop();

		instance.set(TRANSACTION, null);
	},

	/*
	* Methods
	*/
	start: function() {
		var instance = this;

		instance.destructor();

		instance.set(ACTIVE, true);

		var transaction = A.io(
			instance.get(URI),
			instance.get(CFG)
		);

		instance.set(TRANSACTION, transaction);
	},

	stop: function() {
		var instance = this;
		var transaction = instance.get(TRANSACTION);

		if (transaction) {
			transaction.abort();
		}
	},

	_parseURL: function(url) {
		var instance = this;
		var cache = instance.get(CACHE);
		var method = instance.get(METHOD);

		// reusing logic to add a timestamp on the url from jQuery 1.3.2
		if ( (cache === false) && (method == GET) ) {
			var ts = +new Date;
			// try replacing _= if it is there
			var ret = url.replace(/(\?|&)_=.*?(&|$)/, '$1_=' + ts + '$2');
			// if nothing was replaced, add timestamp to the end
			url = ret + ((ret == url) ? (url.match(/\?/) ? '&' : '?') + '_=' + ts : '');
		}

		// formatting the URL with the default uriFormatter after the cache timestamp was added
		var uriFormatter = defaults.uriFormatter;

		if (isFunction(uriFormatter)) {
			url = uriFormatter.apply(instance, [url]);
		}

		return url;
	},

	/*
	* IO callbacks
	*/
	_end: function(id) {
		var instance = this;

		instance.set(ACTIVE, false);
		instance.set(TRANSACTION, null);

		instance.fire(END, id);
	},

	_success: function(id, obj) {
		var instance = this;

		// update the responseData attribute with the new data from xhr
		instance.set(RESPONSE_DATA, obj);

		instance.fire(SUCCESS, id, obj);
	},

	/*
	* Setters
	*/
	_setResponseData: function(xhr) {
		var data = null;
		var instance = this;

		if (xhr) {
			var dataType = instance.get(DATA_TYPE);
			var contentType = xhr.getResponseHeader(CONTENT_TYPE);

			// if the dataType or the content-type is XML...
			if ((dataType == XML) ||
				(!dataType && contentType.indexOf(XML) >= 0)) {

				// use responseXML
				data = xhr.responseXML;

				// check if the XML was parsed correctly
				if (data.documentElement.tagName == 'parsererror') {
					throw PARSE_ERROR;
				}
			}
			else {
				// otherwise use the responseText
				data = xhr.responseText;
			}

			// empty string is not a valid JSON, convert it to null
			if (data === EMPTY_STRING) {
				data = null;
			}

			// trying to parse to JSON if dataType is a valid json
			if (dataType == JSON) {
				try {
					data = A.JSON.parse(data);
				}
				catch(e) {
					// throw PARSE_ERROR;
				}
			}
		}

		return data;
	}
});

A.IORequest = IORequest;

A.io.request = function(uri, config) {
	return new A.IORequest(
		A.merge(config, {
			uri: uri
		})
	);
};<commit_msg>Documentation - IORequest<commit_after>/**
 * The IORequest Utility
 *
 * @module aui-io-request
 */

var L = A.Lang,
	isBoolean = L.isBoolean,
	isFunction = L.isFunction,
	isString = L.isString,

	defaults = AUI.defaults.io,

	getDefault = function(attr) {
		return function() {
			return defaults[attr];
		};
	},

	ACTIVE = 'active',
	ARGUMENTS = 'arguments',
	AUTO_LOAD = 'autoLoad',
	CACHE = 'cache',
	CFG = 'cfg',
	COMPLETE = 'complete',
	CONTENT_TYPE = 'content-type',
	CONTEXT = 'context',
	DATA = 'data',
	DATA_TYPE = 'dataType',
	EMPTY_STRING = '',
	END = 'end',
	FAILURE = 'failure',
	FORM = 'form',
	GET = 'get',
	HEADERS = 'headers',
	IO_REQUEST = 'IORequest',
	JSON = 'json',
	METHOD = 'method',
	RESPONSE_DATA = 'responseData',
	START = 'start',
	SUCCESS = 'success',
	SYNC = 'sync',
	TIMEOUT = 'timeout',
	TRANSACTION = 'transaction',
	URI = 'uri',
	XDR = 'xdr',
	XML = 'xml',

	PARSE_ERROR = 'Parser error: IO dataType is not correctly parsing',

	ACCEPTS = {
		all: '*/*',
		html: 'text/html',
		json: 'application/json, text/javascript',
		text: 'text/plain',
		xml: 'application/xml, text/xml'
	};

/**
 * A base class for IORequest, providing:
 *

 *
Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)

 *

 *

 *
 * Quick Example:

 *
 *
var instance = new A.IORequest({
    boundingBox: ''
}).render();
 *

 *
 * Check the list of Configuration Attributes available for
 * IORequest.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class IORequest
 * @constructor
 * @extends Plugin.Base
 */
function IORequest() {
	IORequest.superclass.constructor.apply(this, arguments);
}

A.mix(IORequest, {
	/**
	 * Static property provides a string to identify the class.
	 *
	 * @property IORequest.NAME
	 * @type String
	 * @static
	 */
	NAME: IO_REQUEST,

	/**
	 * Static property used to define the default attribute
	 * configuration for the IORequest.
	 *
	 * @property IORequest.ATTRS
	 * @type Object
	 * @static
	 */
	ATTRS: {
		/**
		 * If true invoke the
         * start method automatically,
         * initializing the IO transaction.
		 *
		 * @attribute autoLoad
		 * @default true
		 * @type boolean
		 */
		autoLoad: {
			value: true,
			validator: isBoolean
		},

		/**
		 * If false the current timestamp will be appended to the
         * url, avoiding the url to be cached.
		 *
		 * @attribute cache
		 * @default true
		 * @type boolean
		 */
		cache: {
			value: true,
			validator: isBoolean
		},

		/**
		 * The type of the request (i.e., could be xml, json, javascript, text).
		 *
		 * @attribute dataType
		 * @default null
		 * @type String
		 */
		dataType: {
			setter: function(v) {
				return (v || EMPTY_STRING).toLowerCase();
			},
			value: null,
			validator: isString
		},

		/**
		 * This is a normalized attribute for the response data. It's useful
         * to retrieve the correct type for the
         * dataType (i.e., in json
         * requests the responseData) is a JSONObject.
		 *
		 * @attribute responseData
		 * @default null
		 * @type String | JSONObject | XMLDocument
		 */
		responseData: {
			setter: function(v) {
				return this._setResponseData(v);
			},
			value: null
		},

		/**
		 * URI to be requested using AJAX.
		 *
		 * @attribute uri
		 * @default null
		 * @type String
		 */
		uri: {
			setter: function(v) {
				return this._parseURL(v);
			},
			value: null,
			validator: isString
		},

		// User readOnly variables

		/**
		 * Whether the transaction is active or not.
		 *
		 * @attribute active
		 * @default false
		 * @type boolean
		 */
		active: {
			value: false,
			validator: isBoolean
		},

		/**
		 * Object containing all the
         * IO Configuration Attributes.
         * This Object is passed to the A.io internally.
		 *
		 * @attribute cfg
		 * @default Object containing all the
         * IO Configuration Attributes.
		 * @type String
		 */
		cfg: {
			getter: function() {
				var instance = this;

				// keep the current cfg object always synchronized with the mapped public attributes
				// when the user call .start() it always retrieve the last set values for each mapped attr
				return {
					arguments: instance.get(ARGUMENTS),
					context: instance.get(CONTEXT),
					data: instance.get(DATA),
					form: instance.get(FORM),
					headers: instance.get(HEADERS),
					method: instance.get(METHOD),
					on: {
						complete: A.bind(instance.fire, instance, COMPLETE),
						end: A.bind(instance._end, instance),
						failure: A.bind(instance.fire, instance, FAILURE),
						start: A.bind(instance.fire, instance, START),
						success: A.bind(instance._success, instance)
					},
					sync: instance.get(SYNC),
					timeout: instance.get(TIMEOUT),
					xdr: instance.get(XDR)
				}
			},
			readOnly: true
		},

		/**
		 * Stores the IO Object of the current transaction.
		 *
		 * @attribute transaction
		 * @default null
		 * @type Object
		 */
		transaction: {
			value: null
		},

		// Configuration Object mapping
		// To take advantages of the Attribute listeners of A.Base
		// See: http://developer.yahoo.com/yui/3/io/

		arguments: {
			valueFn: getDefault(ARGUMENTS)
		},

		context: {
			valueFn: getDefault(CONTEXT)
		},

		data: {
			valueFn: getDefault(DATA)
		},

		form: {
			valueFn: getDefault(FORM)
		},

		/**
		 * Set the correct ACCEPT header based on the dataType.
		 *
		 * @attribute headers
		 * @default Object
		 * @type Object
		 */
		headers: {
			getter: function(value) {
				var header = [];
				var instance = this;
				var dataType = instance.get(DATA_TYPE);

				if (dataType) {
					header.push(
						ACCEPTS[dataType]
					);
				}

				// always add *.* to the accept header
				header.push(
					ACCEPTS.all
				);

				return A.merge(
					value,
					{
						Accept: header.join(', ')
					}
				);
			},
			valueFn: getDefault(HEADERS)
		},

		/**
		 * See method.
		 *
		 * @attribute method
		 * @default Value mapped on AUI.defaults.io.
		 * @type String
		 */
		method: {
			valueFn: getDefault(METHOD)
		},

		/**
		 * See sync.
		 *
		 * @attribute sync
		 * @default Value mapped on AUI.defaults.io.
		 * @type boolean
		 */
		sync: {
			valueFn: getDefault(SYNC)
		},

		/**
		 * See timeout.
		 *
		 * @attribute timeout
		 * @default Value mapped on AUI.defaults.io.
		 * @type Number
		 */
		timeout: {
			valueFn: getDefault(TIMEOUT)
		},

		/**
		 * See xdr.
		 *
		 * @attribute xdr
		 * @default Value mapped on AUI.defaults.io.
		 * @type Object
		 */
		xdr: {
			valueFn: getDefault(XDR)
		}
	}
});

A.extend(IORequest, A.Plugin.Base, {
	/**
	 * Construction logic executed during IORequest instantiation. Lifecycle.
	 *
	 * @method initializer
	 * @protected
	 */
	initializer: function(config) {
		var instance = this;

		instance.after('init', instance._afterInit);
	},

	/**
	 * Fires after the init phase of the IORequest.
	 *
	 * @method
	 * @param {EventFacade} event
	 * @protected
	 */
	_afterInit: function(event) {
		var instance = this;

		if (instance.get(AUTO_LOAD)) {
			instance.start();
		}
	},

	/**
	 * Descructor lifecycle implementation for the IORequest class.
	 * Purges events attached to the node (and all child nodes).
	 *
	 * @method destructor
	 * @protected
	 */
	destructor: function() {
		var instance = this;

		instance.stop();

		instance.set(TRANSACTION, null);
	},

	/**
	 * Starts the IO transaction. Used to refresh the content also.
	 *
	 * @method start
	 */
	start: function() {
		var instance = this;

		instance.destructor();

		instance.set(ACTIVE, true);

		var transaction = A.io(
			instance.get(URI),
			instance.get(CFG)
		);

		instance.set(TRANSACTION, transaction);
	},

	/**
	 * Stops the IO transaction.
	 *
	 * @method stop
	 */
	stop: function() {
		var instance = this;
		var transaction = instance.get(TRANSACTION);

		if (transaction) {
			transaction.abort();
		}
	},

	/**
	 * Parse the uri to add a
     * timestamp if cache is
     * true. Also applies the
     * AUI.defaults.io.uriFormatter.
	 *
	 * @method _parseURL
	 * @param {String} url
	 * @protected
	 * @return {String}
	 */
	_parseURL: function(url) {
		var instance = this;
		var cache = instance.get(CACHE);
		var method = instance.get(METHOD);

		// reusing logic to add a timestamp on the url from jQuery 1.3.2
		if ( (cache === false) && (method == GET) ) {
			var ts = +new Date;
			// try replacing _= if it is there
			var ret = url.replace(/(\?|&)_=.*?(&|$)/, '$1_=' + ts + '$2');
			// if nothing was replaced, add timestamp to the end
			url = ret + ((ret == url) ? (url.match(/\?/) ? '&' : '?') + '_=' + ts : '');
		}

		// formatting the URL with the default uriFormatter after the cache timestamp was added
		var uriFormatter = defaults.uriFormatter;

		if (isFunction(uriFormatter)) {
			url = uriFormatter.apply(instance, [url]);
		}

		return url;
	},

	/**
	 * Internal end callback for the IO transaction.
	 *
	 * @method _end
	 * @param {Number} id ID of the IO transaction.
	 * @protected
	 */
	_end: function(id) {
		var instance = this;

		instance.set(ACTIVE, false);
		instance.set(TRANSACTION, null);

		instance.fire(END, id);
	},

	/**
	 * Internal success callback for the IO transaction.
	 *
	 * @method _success
	 * @param {Number} id ID of the IO transaction.
	 * @param {Object} obj IO transaction Object.
	 * @protected
	 */
	_success: function(id, obj) {
		var instance = this;

		// update the responseData attribute with the new data from xhr
		instance.set(RESPONSE_DATA, obj);

		instance.fire(SUCCESS, id, obj);
	},

	/**
	 * Setter for responseData.
	 *
	 * @method _setResponseData
	 * @protected
	 * @param {Object} xhr XHR Object.
	 * @return {Object}
	 */
	_setResponseData: function(xhr) {
		var data = null;
		var instance = this;

		if (xhr) {
			var dataType = instance.get(DATA_TYPE);
			var contentType = xhr.getResponseHeader(CONTENT_TYPE);

			// if the dataType or the content-type is XML...
			if ((dataType == XML) ||
				(!dataType && contentType.indexOf(XML) >= 0)) {

				// use responseXML
				data = xhr.responseXML;

				// check if the XML was parsed correctly
				if (data.documentElement.tagName == 'parsererror') {
					throw PARSE_ERROR;
				}
			}
			else {
				// otherwise use the responseText
				data = xhr.responseText;
			}

			// empty string is not a valid JSON, convert it to null
			if (data === EMPTY_STRING) {
				data = null;
			}

			// trying to parse to JSON if dataType is a valid json
			if (dataType == JSON) {
				try {
					data = A.JSON.parse(data);
				}
				catch(e) {
					// throw PARSE_ERROR;
				}
			}
		}

		return data;
	}
});

A.IORequest = IORequest;

/**
 * Alloy IO extension
 *
 * @class A.io
 * @static
 */

/**
 * Static method to invoke the IORequest. Likewise io.
 *
 * @method A.io.request
 * @for A.io
 * @param {String} uri URI to be requested.
 * @param {Object} config Configuration Object for the IO.
 * @return {IORequest}
 */
A.io.request = function(uri, config) {
	return new A.IORequest(
		A.merge(config, {
			uri: uri
		})
	);
};<|endoftext|>