<commit_before>import React from 'react'
import { NumericInput } from './NumericInput'
import { TEXT_FIELDS, VALIDATION_MESSAGES, VALIDATION_TYPES } from '../../utils/constants'
import renderer from 'react-test-renderer'
import Adapter from 'enzyme-adapter-react-15'
import { configure, mount } from 'enzyme'

const COMPONENT_STATE = {
  VALUE: 'value',
  PRISTINE: 'pristine',
  VALID: 'valid'
}
const INPUT_EVENT = {
  KEYPRESS: 'keypress',
  CHANGE: 'change',
  PASTE: 'paste'
}

let mock
let keypressMock
let pasteMock
let numericInputComponent

configure({ adapter: new Adapter() })

beforeEach(() => {
  mock = { target: { value: '' } }

  keypressMock = { key: '1', preventDefault: jest.fn() }

  pasteMock = {
    preventDefault: jest.fn(),
    clipboardData: {
      getData: () => 'e123e123'
    }
  }

  numericInputComponent = {
    side: 'left',
    title: TEXT_FIELDS.DECIMALS,
    description:
      'Refers to how divisible a token can be, from 0 (not at all divisible) to 18 (pretty much continuous).',
    errorMessage: VALIDATION_MESSAGES.DECIMALS,
    onValueUpdate: jest.fn()
  }
})

describe('NumericInput', () => {
  it('Should render the component', () => {
    numericInputComponent.min = '0'
    numericInputComponent.max = '18'
    numericInputComponent.acceptFloat = true
    numericInputComponent.minDecimals = '0'
    numericInputComponent.maxDecimals = '4'

    const component = renderer.create(React.createElement(NumericInput, numericInputComponent))
    const tree = component.toJSON()

    expect(tree).toMatchSnapshot()
  })

  it('Should validate min', () => {
    numericInputComponent.min = 5
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    mock.target.value = '4'
    const expectedInvalidValue = parseFloat(mock.target.value)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper.state(COMPONENT_STATE.VALUE)).toBe(expectedInvalidValue)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

    mock.target.value = '8'
    const expectedValidValue = parseFloat(mock.target.value)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper.state(COMPONENT_STATE.VALUE)).toBe(expectedValidValue)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
  })

  it('Should validate max', () => {
    numericInputComponent.max = 15
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    mock.target.value = '20'
    const expectedInvalidValue = parseFloat(mock.target.value)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper.state(COMPONENT_STATE.VALUE)).toBe(expectedInvalidValue)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

    mock.target.value = '10'
    const expectedValidValue = parseFloat(mock.target.value)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper.state(COMPONENT_STATE.VALUE)).toBe(expectedValidValue)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
  })

  it('Should consider empty string as valid', () => {
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(numericInputComponent.onValueUpdate).toHaveBeenCalled()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
  })

  it('Should prevent pasting invalid value', () => {
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    input.simulate(INPUT_EVENT.PASTE, pasteMock)
    expect(pasteMock.preventDefault).toHaveBeenCalled()
  })

  it('Should allow pasting valid value', () => {
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    pasteMock.clipboardData.getData = () => '12'

    input.simulate(INPUT_EVENT.PASTE, pasteMock)
    expect(pasteMock.preventDefault).toHaveBeenCalledTimes(0)
  })

  it('Should call onValueUpdate callback on successful update', () => {
    const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
    const input = wrapper.find('input').at(0)

    mock.target.value = '10'
    const expectedValue = parseFloat(mock.target.value)

    input.simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper.state(COMPONENT_STATE.VALUE)).toBe(expectedValue)
    expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)

    expect(numericInputComponent.onValueUpdate).toHaveBeenCalledTimes(1)
    expect(numericInputComponent.onValueUpdate).toHaveBeenCalledWith(expectedValue)
  })

  describe('float numbers', () => {
    it ('Should validate maxDecimals', () => {
      numericInputComponent.acceptFloat = true
      numericInputComponent.maxDecimals = '4'
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      mock.target.value = '1.12345'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

      mock.target.value = '1.1234'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it ('Should validate minDecimals', () => {
      numericInputComponent.acceptFloat = true
      numericInputComponent.minDecimals = '2'
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      mock.target.value = '1.1'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

      mock.target.value = '1.1234'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it ('Should validate minDecimals and maxDecimals', () => {
      numericInputComponent.acceptFloat = true
      numericInputComponent.maxDecimals = '4'
      numericInputComponent.minDecimals = '2'
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      mock.target.value = '1.1'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

      mock.target.value = '1.12345'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)

      mock.target.value = '1.12'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)

      mock.target.value = '1.123'
      input.simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper.state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper.state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it('Should reject float with dot notation', () => {
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = '.'
      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalled()
    })

    it('Should accept float with dot notation', () => {
      numericInputComponent.acceptFloat = true
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = '.'
      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
    })

    it('Should reject float with scientific notation', () => {
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = 'e'
      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalled()
    })

    it('Should accept float with scientific notation', () => {
      numericInputComponent.acceptFloat = true
      const wrapper = mount(React.createElement(NumericInput, numericInputComponent))
      const input = wrapper.find('input').at(0)

      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = 'e'
      input.simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
    })

  })
})
<commit_msg>Update NumericInput tests<commit_after>import React from 'react'
import { NumericInput } from './NumericInput'
import { TEXT_FIELDS, VALIDATION_MESSAGES, VALIDATION_TYPES } from '../../utils/constants'
import renderer from 'react-test-renderer'
import Adapter from 'enzyme-adapter-react-15'
import { configure, mount } from 'enzyme'

const COMPONENT_STATE = {
  VALUE: 'value',
  PRISTINE: 'pristine',
  VALID: 'valid'
}
const INPUT_EVENT = {
  KEYPRESS: 'keypress',
  CHANGE: 'change',
  PASTE: 'paste'
}

let mock
let keypressMock
let pasteMock
let numericInputComponent
let wrapperMemo
let wrapper
let inputMemo
let input

configure({ adapter: new Adapter() })

beforeEach(() => {
  mock = { target: { value: '' } }

  keypressMock = { key: '1', preventDefault: jest.fn() }

  pasteMock = {
    preventDefault: jest.fn(),
    clipboardData: {
      getData: () => 'e123e123'
    }
  }

  numericInputComponent = {
    side: 'left',
    title: TEXT_FIELDS.DECIMALS,
    description:
      'Refers to how divisible a token can be, from 0 (not at all divisible) to 18 (pretty much continuous).',
    errorMessage: VALIDATION_MESSAGES.DECIMALS,
    onValueUpdate: jest.fn()
  }

  wrapperMemo = undefined
  wrapper = () => wrapperMemo || (wrapperMemo = mount(React.createElement(NumericInput, numericInputComponent)))

  inputMemo = undefined
  input = () => inputMemo || (inputMemo = wrapper().find('input').at(0))
})

describe('NumericInput', () => {
  it('Should render the component', () => {
    numericInputComponent.min = 0
    numericInputComponent.max = 18
    numericInputComponent.acceptFloat = true
    numericInputComponent.minDecimals = 0
    numericInputComponent.maxDecimals = 4

    expect(renderer.create(React.createElement(NumericInput, numericInputComponent)).toJSON()).toMatchSnapshot()
  })

  it('Should fail if value is less than min', () => {
    numericInputComponent.min = 5
    mock.target.value = '4'

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(parseFloat(mock.target.value))
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
  })

  it('Should pass if value is greater than min', () => {
    numericInputComponent.min = 5
    mock.target.value = '8'

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(parseFloat(mock.target.value))
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
  })

  it('Should validate max', () => {
    numericInputComponent.max = 15
    mock.target.value = '20'

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(parseFloat(mock.target.value))
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
  })

  it('Should validate max', () => {
    numericInputComponent.max = 15
    mock.target.value = '10'

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(parseFloat(mock.target.value))
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
  })

  it('Should consider empty string as valid', () => {
    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(numericInputComponent.onValueUpdate).toHaveBeenCalled()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
  })

  it('Should accept "-" symbol if min is negative', () => {
    numericInputComponent.min = -10
    keypressMock.key = '-'

    input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
    expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
  })

  it('Should accept "-" symbol if max is negative', () => {
    numericInputComponent.max = -10
    keypressMock.key = '-'

    input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
    expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
  })

  it('Should reject "-" symbol if min is not negative', () => {
    numericInputComponent.min = 0
    keypressMock.key = '-'

    input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
    expect(keypressMock.preventDefault).toHaveBeenCalled()
  })

  it('Should reject "-" symbol if max is not negative', () => {
    numericInputComponent.max = 10
    keypressMock.key = '-'

    input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
    expect(keypressMock.preventDefault).toHaveBeenCalled()
  })

  it('Should reject "-" symbol if it is not the first character', () => {
    numericInputComponent.min = -10
    mock.target.value = 5
    keypressMock.key = '-'

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(5)

    input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
    expect(keypressMock.preventDefault).toHaveBeenCalled()
  })

  it('Should prevent pasting invalid value', () => {
    input().simulate(INPUT_EVENT.PASTE, pasteMock)
    expect(pasteMock.preventDefault).toHaveBeenCalled()
  })

  it('Should allow pasting valid value', () => {
    pasteMock.clipboardData.getData = () => '12'

    input().simulate(INPUT_EVENT.PASTE, pasteMock)
    expect(pasteMock.preventDefault).toHaveBeenCalledTimes(0)
  })

  it('Should call onValueUpdate callback on successful update', () => {
    mock.target.value = '10'
    const expectedValue = parseFloat(mock.target.value)

    input().simulate(INPUT_EVENT.CHANGE, mock)
    expect(wrapper().state(COMPONENT_STATE.VALUE)).toBe(expectedValue)
    expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
    expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    expect(numericInputComponent.onValueUpdate).toHaveBeenCalledTimes(1)
    expect(numericInputComponent.onValueUpdate).toHaveBeenCalledWith(expectedValue)
  })

  describe('float numbers', () => {
    beforeEach(() => {
      numericInputComponent.acceptFloat = true
      numericInputComponent.minDecimals = 2
      numericInputComponent.maxDecimals = 4
    })

    it('Should fail if value has more decimals than maxDecimals', () => {
      mock.target.value = '1.12345'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
    })

    it('Should pass if value has less decimals than maxDecimals', () => {
      mock.target.value = '1.123'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it('Should pass if value has same decimals than maxDecimals', () => {
      mock.target.value = '1.1234'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it('Should fail if value has less decimals than minDecimals', () => {
      mock.target.value = '1.1'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
    })

    it('Should pass if value has more decimals than minDecimals', () => {
      mock.target.value = '1.1234'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    it('Should pass if value has same decimals than minDecimals', () => {
      mock.target.value = '1.12'

      input().simulate(INPUT_EVENT.CHANGE, mock)
      expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
      expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
    })

    describe('range of [minDecimals, maxDecimals]', () => {
      it('Should fail for: 1.1, if it is outside the range', () => {
        mock.target.value = '1.1'

        input().simulate(INPUT_EVENT.CHANGE, mock)
        expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
        expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
      })

      it('Should fail for: 1.12345, if it is outside the range', () => {
        mock.target.value = '1.12345'

        input().simulate(INPUT_EVENT.CHANGE, mock)
        expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
        expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.INVALID)
      })

      it('Should pass for: 1.12, if it is inside the range', () => {
        mock.target.value = '1.12'

        input().simulate(INPUT_EVENT.CHANGE, mock)
        expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
        expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
      })

      it('Should pass for: 1.123, if it is inside the range', () => {
        mock.target.value = '1.123'

        input().simulate(INPUT_EVENT.CHANGE, mock)
        expect(wrapper().state(COMPONENT_STATE.PRISTINE)).toBeFalsy()
        expect(wrapper().state(COMPONENT_STATE.VALID)).toBe(VALIDATION_TYPES.VALID)
      })
    })

    it('Should reject float with dot notation', () => {
      numericInputComponent.acceptFloat = false

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = '.'

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalled()
    })

    it('Should accept float with dot notation', () => {
      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = '.'

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
    })

    it('Should reject float with scientific notation', () => {
      numericInputComponent.acceptFloat = false

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = 'e'

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalled()
    })

    it('Should accept float with scientific notation', () => {
      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)

      keypressMock.key = 'e'

      input().simulate(INPUT_EVENT.KEYPRESS, keypressMock)
      expect(keypressMock.preventDefault).toHaveBeenCalledTimes(0)
    })
  })
})
<|endoftext|>


<commit_before>import {inject} from 'aurelia-dependency-injection';
import {customElement, bindable} from 'aurelia-templating';
import {WidgetBase} from '../common/widget-base';
import {generateBindables} from '../common/decorators';
import {constants} from '../common/constants';
import 'kendo-ui/js/kendo.all.min';

@customElement(`${constants.elementPrefix}map`)
@generateBindables('kendoMap')
@inject(Element, WidgetBase)
export class Map {

  @bindable options = {};

  constructor(element, widgetBase, viewResources) {
    this.element = element;
    this.widgetBase = widgetBase
                    .control('kendoMap')
                    .linkViewModel(this)
                    .useValueBinding();
  }

  bind(ctx) {
    this.$parent = ctx;
  }

  attached() {
    this.recreate();
  }

  recreate() {
    this.kWidget = this.widgetBase.createWidget({
      element: this.element,
      parentCtx: this.$parent
    });
  }

  propertyChanged(property, newValue, oldValue) {
    this.widgetBase.handlePropertyChanged(this.kWidget, property, newValue, oldValue);
  }

  detached() {
    this.widgetBase.destroy(this.kWidget);
  }
}
<commit_msg>fix(wrapper): map control has no value<commit_after>import {inject} from 'aurelia-dependency-injection';
import {customElement, bindable} from 'aurelia-templating';
import {WidgetBase} from '../common/widget-base';
import {generateBindables} from '../common/decorators';
import {constants} from '../common/constants';
import 'kendo-ui/js/kendo.all.min';

@customElement(`${constants.elementPrefix}map`)
@generateBindables('kendoMap')
@inject(Element, WidgetBase)
export class Map {

  @bindable options = {};

  constructor(element, widgetBase, viewResources) {
    this.element = element;
    this.widgetBase = widgetBase
                    .control('kendoMap')
                    .linkViewModel(this);
  }

  bind(ctx) {
    this.$parent = ctx;
  }

  attached() {
    this.recreate();
  }

  recreate() {
    this.kWidget = this.widgetBase.createWidget({
      element: this.element,
      parentCtx: this.$parent
    });
  }

  propertyChanged(property, newValue, oldValue) {
    this.widgetBase.handlePropertyChanged(this.kWidget, property, newValue, oldValue);
  }

  detached() {
    this.widgetBase.destroy(this.kWidget);
  }
}
<|endoftext|>


<commit_before>/*
 * Return an array consisting of the largest number from each provided sub-array.
 * For simplicity, the provided array will contain exactly 4 sub-arrays.
 * Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i].
 */

function largestOfFour(arr) {
  var results = [];
  for(var r = 0; r < arr.length; r++){
    var largestNum = arr[r][0];
    for(var c = 1; c < arr[r].length; c++){
      if(arr[r][c] > largestNum){
        largestNum = arr[r][c];
      }
    }
    results[r] = largestNum;
  }
  // You can do this!
  return results;
}

//test method
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
<commit_msg>more indentation<commit_after>/*
 * Return an array consisting of the largest number from each provided sub-array.
 * For simplicity, the provided array will contain exactly 4 sub-arrays.
 * Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i].
 */

function largestOfFour(arr) {
  var results = [];
  for(var r = 0; r < arr.length; r++){
     var largestNum = arr[r][0];
     for(var c = 1; c < arr[r].length; c++){
        if(arr[r][c] > largestNum){
           largestNum = arr[r][c];
        }
     }
     results[r] = largestNum;
  }
  // You can do this!
  return results;
}

//test method
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
<|endoftext|>


<commit_before>define("ace/mode/sparql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"], function(require, exports, module) {
/*var _ = {require: require, exports: exports, module: module};
exports = undefined; module = undefined;
function define(name, deps, m) {
    if (typeof name == "function") {
        m = name; deps = ["require", "exports", "module"]; name = _.module.id
    }
    if (typeof name == "object") {
        m = deps; deps = name; name = _.module.id
    }
    if (typeof deps == "function") {
        m = deps; deps = [];
    }
   var ret = m.apply(_.module, deps.map(function(n){return _[n] || require(n)}))
   if (ret) _.module.exports = ret;
}
define.amd = true;define("ace/mode/sparql_highlight_rules", function(require, exports, module) {*/

var oop = require("../lib/oop");
var lang = require("../lib/lang");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var SparqlHighlightRules = function() {

  var builtinFunctions_str = "str|lang|langmatches|datatype|bound|sameterm|isiri|isuri|isblank|isliteral|union|a|count|number";
  var builtinFunctions = lang.arrayToMap(builtinFunctions_str.split("|"));
  var keyword_str = "BASE|PREFIX|SELECT|ASK|CONSTRUCT|DESCRIBE|WHERE|FROM|REDUCED|NAMED|ORDER|LIMIT|OFFSET|FILTER|OPTIONAL|GRAPH|BY|ASC|DESC|UNION|MINUS";

  var keywords = lang.arrayToMap(keyword_str.split("|"));

  var buildinConstants = "true|false".split("|");

  this.$keywords = keyword_str.split("|");
  Array.prototype.push.apply(this.$keywords, builtinFunctions_str.split("|"));

  var builtinVariables = lang.arrayToMap(
    ("").split("|")
  );

  this.$rules = {
    "start" : [
      {
        token : "comment",
        regex : "#.*$"
      }, {
        token : "sparql.constant.uri",
        regex : "\\<\\S+\\>"
      }, {
        token : "sparql.variable",
        regex : "[\\?\\$][a-zA-Z_][a-zA-Z_0-9]*"
      }, {
        token : "sparql.prefix.constant.language",
        regex : "[a-zA-Z]+:"
      }, {
        token : "string.regexp",
        regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
      }, {
        token : "string", // single line
        regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
      }, {
        token : "string", // single line
        regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
      }, {
        token : "constant.numeric", // hex
        regex : "0[xX][0-9a-fA-F]+\\b"
      }, {
        token : "constant.numeric", // float
        regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
      }, {
        token : "constant.language.boolean",
        regex : "(?:true|false)\\b"
      }, {
        token : function(value) {
          if (value == "self")
            return "variable.language";
          else if (keywords.hasOwnProperty(value))
            return "keyword";
          else if (buildinConstants.hasOwnProperty(value))
            return "constant.language";
          else if (builtinVariables.hasOwnProperty(value))
            return "variable.language";
          else if (builtinFunctions.hasOwnProperty(value))
            return "support.function";
          else if (value == "debugger")
            return "invalid.deprecated";
          else
            return "identifier";
        },
        regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
      }, {
        token : "keyword.operator",
        regex : "\\*|\\+|\\|\\-|\\<|\\>|=|&|\\|"
      }, {
        token : "lparen",
        regex : "[\\<({]"
      }, {
        token : "rparen",
        regex : "[\\>)}]"
      }, {
        token : "text",
        regex : "\\s+"
      }, {
		caseInsensitive: true
	  }
    ],
    "comment" : [
      {
        token : "comment", // comment spanning whole line
        regex : ".+"
      }
    ]
  };
};

oop.inherits(SparqlHighlightRules, TextHighlightRules);
exports.SparqlHighlightRules = SparqlHighlightRules;
});//});

define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) {
"use strict";

var Range = require("../range").Range;

var MatchingBraceOutdent = function() {

(function() {

    this.checkOutdent = function(line, input) {
        if (! /^\s+$/.test(line))
            return false;

        return /^\s*\}/.test(input);
    };

    this.autoOutdent = function(doc, row) {
        var line = doc.getLine(row);
        var match = line.match(/^(\s*\})/);

        if (!match) return 0;

        var column = match[1].length;
        var openBracePos = doc.findMatchingBracket({row: row, column: column});

        if (!openBracePos || openBracePos.row == row) return 0;

        var indent = this.$getIndent(doc.getLine(openBracePos.row));
        doc.replace(new Range(row, 0, row, column-1), indent);
    };

    this.$getIndent = function(line) {
        return line.match(/^\s*/)[0];
    };

}).call(MatchingBraceOutdent.prototype);

exports.MatchingBraceOutdent = MatchingBraceOutdent;
};
});

define("ace/mode/sparql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sparql_highlight_rules","ace/mode/matching_brace_outdent","ace/range"], function(require, exports, module) {
/*var _ = {require: require, exports: exports, module: module};
exports = undefined; module = undefined;
function define(name, deps, m) {
    if (typeof name == "function") {
        m = name; deps = ["require", "exports", "module"]; name = _.module.id
    }
    if (typeof name == "object") {
        m = deps; deps = name; name = _.module.id
    }
    if (typeof deps == "function") {
        m = deps; deps = [];
    }
   var ret = m.apply(_.module, deps.map(function(n){return _[n] || require(n)}))
   if (ret) _.module.exports = ret;
}

define.amd = true;define("ace/mode/sparql", function(require, exports, module) {*/
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var Tokenizer = require("../tokenizer").Tokenizer;
var SparqlHighlightRules = require("./sparql_highlight_rules").SparqlHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;

var Mode = function() {
  this.$tokenizer = new Tokenizer(new SparqlHighlightRules().getRules());
  this.$highlightRules = new SparqlHighlightRules();
  this.$highlightRules.$meta = "SPARQL Core";
  this.$highlightRules.$keywordList = this.$highlightRules.$keywords;
};
oop.inherits(Mode, TextMode);

exports.Mode = Mode;

});
//});
<commit_msg>Made SparQL editor case insensitive<commit_after>define("ace/mode/sparql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"], function(require, exports, module) {
/*var _ = {require: require, exports: exports, module: module};
exports = undefined; module = undefined;
function define(name, deps, m) {
    if (typeof name == "function") {
        m = name; deps = ["require", "exports", "module"]; name = _.module.id
    }
    if (typeof name == "object") {
        m = deps; deps = name; name = _.module.id
    }
    if (typeof deps == "function") {
        m = deps; deps = [];
    }
   var ret = m.apply(_.module, deps.map(function(n){return _[n] || require(n)}))
   if (ret) _.module.exports = ret;
}
define.amd = true;define("ace/mode/sparql_highlight_rules", function(require, exports, module) {*/

var oop = require("../lib/oop");
var lang = require("../lib/lang");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var SparqlHighlightRules = function() {

  var builtinFunctions_str = "str|lang|langmatches|datatype|bound|sameterm|isiri|isuri|isblank|isliteral|union|a|count|number";
  var builtinFunctions = lang.arrayToMap(builtinFunctions_str.split("|"));
  var keyword_str = "BASE|PREFIX|SELECT|ASK|CONSTRUCT|DESCRIBE|WHERE|FROM|REDUCED|NAMED|ORDER|LIMIT|OFFSET|FILTER|OPTIONAL|GRAPH|BY|ASC|DESC|UNION|MINUS";

  var keywords = lang.arrayToMap(keyword_str.split("|"));

  var buildinConstants = "true|false".split("|");

  this.$keywords = keyword_str.split("|");
  Array.prototype.push.apply(this.$keywords, builtinFunctions_str.split("|"));

  var builtinVariables = lang.arrayToMap(
    ("").split("|")
  );

  this.$rules = {
    "start" : [
      {
        token : "comment",
        regex : "#.*$"
      }, {
        token : "sparql.constant.uri",
        regex : "\\<\\S+\\>"
      }, {
        token : "sparql.variable",
        regex : "[\\?\\$][a-zA-Z_][a-zA-Z_0-9]*"
      }, {
        token : "sparql.prefix.constant.language",
        regex : "[a-zA-Z]+:"
      }, {
        token : "string.regexp",
        regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
      }, {
        token : "string", // single line
        regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
      }, {
        token : "string", // single line
        regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
      }, {
        token : "constant.numeric", // hex
        regex : "0[xX][0-9a-fA-F]+\\b"
      }, {
        token : "constant.numeric", // float
        regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
      }, {
        token : "constant.language.boolean",
        regex : "(?:true|false)\\b"
      }, {
        token : function(value) {
          if (value == "self")
            return "variable.language";
          else if (keywords.hasOwnProperty(value.toUpperCase()))
            return "keyword";
          else if (buildinConstants.hasOwnProperty(value.toUpperCase()))
            return "constant.language";
          else if (builtinVariables.hasOwnProperty(value))
            return "variable.language";
          else if (builtinFunctions.hasOwnProperty(value.toLowerCase()))
            return "support.function";
          else if (value == "debugger")
            return "invalid.deprecated";
          else
            return "identifier";
        },
        regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
      }, {
        token : "keyword.operator",
        regex : "\\*|\\+|\\|\\-|\\<|\\>|=|&|\\|"
      }, {
        token : "lparen",
        regex : "[\\<({]"
      }, {
        token : "rparen",
        regex : "[\\>)}]"
      }, {
        token : "text",
        regex : "\\s+"
      }, {
		caseInsensitive: true
	  }
    ],
    "comment" : [
      {
        token : "comment", // comment spanning whole line
        regex : ".+"
      }
    ]
  };
};

oop.inherits(SparqlHighlightRules, TextHighlightRules);
exports.SparqlHighlightRules = SparqlHighlightRules;
});//});

define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) {
"use strict";

var Range = require("../range").Range;

var MatchingBraceOutdent = function() {

(function() {

    this.checkOutdent = function(line, input) {
        if (! /^\s+$/.test(line))
            return false;

        return /^\s*\}/.test(input);
    };

    this.autoOutdent = function(doc, row) {
        var line = doc.getLine(row);
        var match = line.match(/^(\s*\})/);

        if (!match) return 0;

        var column = match[1].length;
        var openBracePos = doc.findMatchingBracket({row: row, column: column});

        if (!openBracePos || openBracePos.row == row) return 0;

        var indent = this.$getIndent(doc.getLine(openBracePos.row));
        doc.replace(new Range(row, 0, row, column-1), indent);
    };

    this.$getIndent = function(line) {
        return line.match(/^\s*/)[0];
    };

}).call(MatchingBraceOutdent.prototype);

exports.MatchingBraceOutdent = MatchingBraceOutdent;
};
});

define("ace/mode/sparql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sparql_highlight_rules","ace/mode/matching_brace_outdent","ace/range"], function(require, exports, module) {
/*var _ = {require: require, exports: exports, module: module};
exports = undefined; module = undefined;
function define(name, deps, m) {
    if (typeof name == "function") {
        m = name; deps = ["require", "exports", "module"]; name = _.module.id
    }
    if (typeof name == "object") {
        m = deps; deps = name; name = _.module.id
    }
    if (typeof deps == "function") {
        m = deps; deps = [];
    }
   var ret = m.apply(_.module, deps.map(function(n){return _[n] || require(n)}))
   if (ret) _.module.exports = ret;
}

define.amd = true;define("ace/mode/sparql", function(require, exports, module) {*/
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var Tokenizer = require("../tokenizer").Tokenizer;
var SparqlHighlightRules = require("./sparql_highlight_rules").SparqlHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var Range = require("../range").Range;

var Mode = function() {
  this.$tokenizer = new Tokenizer(new SparqlHighlightRules().getRules());
  this.$highlightRules = new SparqlHighlightRules();
  this.$highlightRules.$meta = "SPARQL Core";
  this.$highlightRules.$keywordList = this.$highlightRules.$keywords;
};
oop.inherits(Mode, TextMode);

exports.Mode = Mode;

});
//});
<|endoftext|>


<commit_before>/**
 * Created by ksinger on 05.11.2015.
 */

/* TODO this fragment is part of an attempt to sketch a different
 * approach to asynchronity (Remove it or the thunk-based
 * solution afterwards)
 */

/*
* This redux wrapper for the old message-service consists of:
*
* * an "agent" that registers with the service, receives messages
* from it and triggers redux actions.
* * an "component" that listens to state changes and triggers
* messages to the server via the service.
 */

import { attach, delay, watchImmutableRdxState} from './utils';
//import './message-service'; //TODO still uses es5
import { actionCreators }  from './actions/actions';

export function runMessagingAgent(redux) {

    const ws = openWebSocket()
    //.then( (ws) => {
        const unsubscribeWatch = watchImmutableRdxState(
            redux, ['enqueuedMessages'],
            (newMq, oldMq) => {
                console.log('old mq length: ', oldMq.size);
                console.log('new mq length: ', newMq.size);
                if (newMq.size > 0) {
                    // a new msg was enqueued
                    const msg = newMq.first();
                    console.log('about to send ', msg);
                    ws.send(msg);
                    redux.dispatch(actionCreators.messages__markAsSent({msg})); //might be necessary to do this async (with `delay(...,0)`)
                }
            }
        );
        //ws.on('receive',...)
        ws.onReceived = (msg) => {

            /* TODO this is only for demo purposes. In practice, more
             * fragmented actions should be called here. Introducing
             * an in-queue would require another agent/more agents in
             * the system that works through the queue and dispatches
             * actions, resulting in the same unpredictability that
             * the pure angular approach had. For modularization handling
             * should be broken down into layered functions in
             * multiple files.
             */
            redux.dispatch(actionCreators.messages__receive({msg}));
        }
    //});
}

let dummyWs = null;
class DummyWs {
    send(msg) {
        console.log('"Sending to server": ', msg);
        delay(1500).then(() => {
            if(this.onReceived) {
                this.onReceived(msg);
            }
        });
    }
}
function openWebSocket() { return dummyWs? dummyWs : new DummyWs() }
<commit_msg>Working on messaging-agent.<commit_after>/**
 * Created by ksinger on 05.11.2015.
 */

/* TODO this fragment is part of an attempt to sketch a different
 * approach to asynchronity (Remove it or the thunk-based
 * solution afterwards)
 */

/*
* This redux wrapper for the old message-service consists of:
*
* * an "agent" that registers with the service, receives messages
* from it and triggers redux actions.
* * an "component" that listens to state changes and triggers
* messages to the server via the service.
 */

import { attach, delay, watchImmutableRdxState} from './utils';
//import './message-service'; //TODO still uses es5
import { actionCreators }  from './actions/actions';
import SockJS from 'sockjs';

export function runMessagingAgent(redux) {

    //const ws = new SockJS('owner/msg', null, {debug: true});
    const ws = openWebSocket();
    ws.onopen = () => {
        /* Set up message-queue watch */
        const unsubscribeWatch = watchImmutableRdxState(
            redux, ['enqueuedMessages'],
            (newMq, oldMq) => {
                console.log('old mq length: ', oldMq.size);
                console.log('new mq length: ', newMq.size);
                if (newMq.size > 0) {
                    // a new msg was enqueued
                    const msg = newMq.first();
                    console.log('about to send ', msg);
                    ws.send(msg);
                    redux.dispatch(actionCreators.messages__markAsSent({msg})); //might be necessary to do this async (with `delay(...,0)`)
                }
            }
        );

    };
    ws.onmessage = (msg) => {
        /* TODO this is only for demo purposes. In practice, more
         * fragmented actions should be called here. Introducing
         * an in-queue would require another agent/more agents in
         * the system that works through the queue and dispatches
         * actions, resulting in the same unpredictability that
         * the pure angular approach had. For modularization handling
         * should be broken down into layered functions in
         * multiple files.
         */
        console.log('got message via websocket: ', msg);
        redux.dispatch(actionCreators.messages__receive({msg}));
    };
    ws.onerror = () => {
    };
    ws.onclose = () => {
    };

    window.ws4dbg = ws;//TODO deletme
}

let dummyWs = null;
class DummyWs {
    constructor(){
        delay(2000).then(() => {
            if(this.onopen) {
                this.onopen()
            }
        });
    }
    send(msg) {
        console.log('"Sending to server": ', msg);
        delay(1500).then(() => {
            if(this.onmessage) {
                this.onmessage(msg);
            }
        });
    }
}
function openWebSocket() { return dummyWs? dummyWs : new DummyWs() }
<|endoftext|>


<commit_before>// Auther : JoMingyu

const express = require('express');
const app = express();

const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));

var login = require('./restful/login.js');
var tree = require('./restful/tree.js');
var forest = require('./restful/forest.js');
var post = require('./restful/post.js');

app.use('', login);
app.use('', tree);
app.use('', forest);
app.use('', post);
// const cookieParser = require('cookie-parser');
// app.use(cookieParser('!..d3##dk!'));

// const session = require('express-session');
// app.use(session({
//     secret: '2k@!kkeSS',
//     resave: false,
//     saveUninitialized: true
// }));

app.use('/', require('./restful/tree.js'));

app.listen(13958, () => {
    console.log('Server is listening:13958');
});
<commit_msg>불필요한 변수 제거<commit_after>// Auther : JoMingyu

const express = require('express');
const app = express();

const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));

// const cookieParser = require('cookie-parser');
// app.use(cookieParser('!..d3##dk!'));

// const session = require('express-session');
// app.use(session({
//     secret: '2k@!kkeSS',
//     resave: false,
//     saveUninitialized: true
// }));

app.use('', require('./restful/login.js'));
app.use('', require('./restful/tree.js'));
app.use('', require('./restful/forest.js'));
app.use('', require('./restful/post.js'));

app.listen(13958, () => {
    console.log('Server is listening:13958');
});
<|endoftext|>


<commit_before>/**
 * Basic View Engine. (Using Mustache.js as templating engine)
 *
 * Plugins (to app)
 * ----------------
 * app.ve
 * app.ve.view
 * app.ve.component
 * app.ve.components
 * app.ve.inject
 * $(el).data('view')
 *
 *
 * Use of View
 * -----------
 * 1. new View({
 * 		template: [name],
 * 		[init]: function(){...}
 * 		[$el]:
 * 		[data]:
 * 		[events]: '<e> <selector>': fn(e) {$(this), e.data.view}
 * })
 * 2. view.render(data, [$el])
 * 3. view.on/($)trigger/once/off()
 * 4. view.teardown()
 * 5. View.extend({...})
 * 6. view.bind() TBI (two-way with binders in tpl)
 * 7. view.vm (available after view.bind())
 *
 *
 * Life cycle
 * ----------
 * init() --> render(e) --> render(e) ... --> teardown(e)
 *
 * *Note*: that due to implemenation constrains (using $el for events) init() will not emit any `initialize` event.
 *
 *
 * Ghost View
 * ----------
 * 1. only views with `$el` can be rendered on screen, otherwise html is returned by `.render()`;
 * 2. only `template` name is required when defining a View, `data` and `$el` can be inserted later using `.render()`;
 * 3. only views with `$el` can register events;
 * 4. rendering same view again and again will not re-register the listeners;
 * 5. rendering a new view on a `$el` will `.teardown()` the previous view if template names are different;
 * 6. `.teardown()` will not `$.remove()` a view's `$el`, but `$.empty()` it and remove all the event listeners;
 *
 * Ghost View will NOT happen in this implementation since jQuery removes data and event handlers from child
 * elements during `$.empty()`. If you render parent `$el` with a new view, child views will be removed properly
 * given that we bind everything on the `$el` through jQuery.
 *
 *
 * Gotcha
 * ------
 * 1. If you use `app.coordinator.on` for co-op with other things in the application, make sure to clean the listener
 * up in the view's `teardown` event.
 * 2. there are no `on<event>` shortcut functions for listeners in a view. use `.on`/`.once` and `options.events` to
 * register them instead.
 *
 *
 * Hardcode
 * --------
 * 1. templates must be named `*.mst.html`
 *
 *
 * @author Tim Lauv <bluekvirus@gmail.com>
 * @created 2015.04.27
 */
(function(_, $, app, Mustache){
	app.ve = {name: 'Basic', _tplSuffix: '.mst.html'};

	//--------------------------------View class definition---------------------------------
	//.template, .$el, .data, init() .render(e), .teardown(e), .events, .once/on/off/trigger()
	//constructor (logic-free)
	var View = function(options){
		this._options = options || {};

		//optional
		this.$el = this._options.el && $(this._options.el);
		this.$el = this._options.$el || this.$el;
		this.data = this._options.data || this.data;
		this.init = this._options.init || this._options.initialize || this.init;
		this.events = this._options.events || this.events;
		this.template = this._options.template || this.template;

		//extension point
		this.init(this._options);
		if(this.$el) this.render();
	};
	//member methods
	_.extend(View.prototype, {
		init: _.noop,

		render: function(data, $el){

			//check the template first!
			if(!this.template) app.throw('View definition requires a template!');
			var tpl = app.templates[this.template] || app.templates[this.template + app.ve._tplSuffix] || this.template;

			//sanitize params
			if(data instanceof jQuery){
				$el = data;
				data = undefined;
			}

			this.$el = $el || this.$el;
			this.data = data || this.data;

			var content = Mustache.render(tpl, this.data);

			if(this.$el) {
				//teardown previous view if template is different.
				var meta = this.$el.data();
				if(!meta) app.throw('Invalid $el upon ' + (this._name || 'view') + '.render(), check your el selector...');
				if(meta.view && (meta.view.template !== this.template))
					meta.view.teardown();

				//re-render but not registering the listeners again.
				this.$el.html(content);
				this.$el.data('view', this);
				if(!this.$el.data('_events_')) {
					//format <e> <selectors>, instead of <e1> <e2> ...
					_.each(this.events, function(fn, namenselector){
						var tmp = _.compact(namenselector.split(' '));
						name = tmp.shift();
						if(_.size(tmp))
							this.$el.on(name, tmp.join(' '), {view: this.$el.data('view')}, fn);
						else
							this.$el.on(name, {view: this.$el.data('view')}, fn);
					}, this);

					this.$el.data('_events_', true);
				}
			}
			else return content;

			this.trigger('render');
			return this;
		},

		teardown: function(){
			if(this.$el){
				this.$el.removeData('_events_', 'view');
				this.$el.empty();
				this.trigger('teardown');
				this.off();
			}
		},

		//dynamic instance events support .once, .trigger
		//use options.events for easy .on listener registration.
		once: function(){
			if(this.$el) {
				this.$el.one.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		on: function(){
			if(this.$el) {
				this.$el.on.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		off: function(){
			if(this.$el) {
				this.$el.off.apply(this.$el, arguments);
			}
		},

		trigger: function(){
			if(this.$el) {
				//note that we use triggerHandler instead of trigger to avoid custom event bubbling
				this.$el.triggerHandler.apply(this.$el, arguments);
			}
		},

		$trigger: function(){
			if(this.$el) {
				//allow event bubbling
				this.$el.trigger.apply(this.$el, arguments);
			}
		}
	});
	//static methods
	_.extend(View, {
		//class inheritance
		extend: function(configure, statics){
			var A = this.prototype.constructor;

			var B = function(){
				A.apply(this, arguments); //instead of A.call(this, arg1, arg2, ...)
			};

			B.prototype = new A(); //logic-free constructor
			_.extend(B.prototype, configure);
			_.extend(B, A, statics);
			//note that `prototype` and `constructor` are non-enumerable, thus won't be copied by _.extend()

			B.prototype.constructor = B;

			return B;
		}
	});

	//-----------------hooks into app infrastructure-------------------
	//convert templates into components
	app.coordinator.on('app.load', function(){

		_.each(app.templates, function(tpl, filename){
			var name = app.tplNameToCompName(filename, app.ve._tplSuffix);
			app.ve.component(name, {
				template: filename
			});

			app.debug('component registered:', name);
		});

		app.coordinator.trigger('app.loaded');
	});

	//----------------apis enhancement to app-------------------------
	app.ve.view = function(options){
		return new View(options);
	};

	app.ve.components = {};
	app.ve.component = function(name, configure){
		if(app.ve.components[name]) {
			//override
			app.ve.components[name] = app.ve.components[name].extend(configure);
		} else
			//register
			app.ve.components[name] = View.extend(_.extend({_name: name}, configure));
		return app.ve.components[name];
	};

		//internal worker for ve.inject (single target, cb(err, result))
	function _inject (options, cb){
		if(!app.isAMDEnabled()) app.throw('AMD is not enabled, use task:dance before ve.inject()');
		if(_.isString(options))
			options = {path: options};
		if(_.isFunction(options)){
			cb = options;
			options = {};
		}
		options = _.extend({
			baseURL: 'vanilla/',
			tplOnly: false,
			forceName: ''
		}, options);
		//allow :static in option.path to indicate tplOnly
		if(_.endsWith(options.path, ':static')){
			options.tplOnly = true;
			options.path = options.path.replace(/:static$/, '');
		}
		var compName = options.forceName?options.forceName:app.tplNameToCompName(options.path);
		var tplTarget = _.endsWith(options.path, '/')?[options.baseURL, options.path, 'index', app.ve._tplSuffix].join(''):[options.baseURL, options.path, app.ve._tplSuffix].join(''),
		jsTarget = tplTarget.replace(app.ve._tplSuffix, '');
		var targets = ['text!' + tplTarget];
		if(!options.tplOnly) targets.push(jsTarget);
		//don't use define here... the cb will never gets invoked. (until what's define()-ed gets required)
		require(targets, function(tpl, js){
			js = js || {};
			//as success cb
			cb(null, app.ve.component(compName, _.extend(js, {template: tpl})));
		}, cb);//as error cb
	}
	//dynamically inject js + html to make a View or multiple View(s)
	app.ve.inject = function (options, cb){
		if(_.isArray(options)){
			app.coordinator.async.map(options, _inject, cb);
		} else {
			_inject(options, cb);
		}
	};

})(_, jQuery, Application, Mustache);<commit_msg>Allow listener fn to be name strings in basic ve View events;<commit_after>/**
 * Basic View Engine. (Using Mustache.js as templating engine)
 *
 * Plugins (to app)
 * ----------------
 * app.ve
 * app.ve.view
 * app.ve.component
 * app.ve.components
 * app.ve.inject
 * $(el).data('view')
 *
 *
 * Use of View
 * -----------
 * 1. new View({
 * 		template: [name],
 * 		[init]: function(){...}
 * 		[$el]:
 * 		[data]:
 * 		[events]: '<e> <selector>': 'fn' or fn(e) {$(this), e.data.view}
 * })
 * 2. view.render(data, [$el])
 * 3. view.on/($)trigger/once/off()
 * 4. view.teardown()
 * 5. View.extend({...})
 * 6. view.bind() TBI (two-way with binders in tpl)
 * 7. view.vm (available after view.bind())
 *
 *
 * Life cycle
 * ----------
 * init() --> render(e) --> render(e) ... --> teardown(e)
 *
 * *Note*: that due to implemenation constrains (using $el for events) init() will not emit any `initialize` event.
 *
 *
 * Ghost View
 * ----------
 * 1. only views with `$el` can be rendered on screen, otherwise html is returned by `.render()`;
 * 2. only `template` name is required when defining a View, `data` and `$el` can be inserted later using `.render()`;
 * 3. only views with `$el` can register events;
 * 4. rendering same view again and again will not re-register the listeners;
 * 5. rendering a new view on a `$el` will `.teardown()` the previous view if template names are different;
 * 6. `.teardown()` will not `$.remove()` a view's `$el`, but `$.empty()` it and remove all the event listeners;
 *
 * Ghost View will NOT happen in this implementation since jQuery removes data and event handlers from child
 * elements during `$.empty()`. If you render parent `$el` with a new view, child views will be removed properly
 * given that we bind everything on the `$el` through jQuery.
 *
 *
 * Gotcha
 * ------
 * 1. If you use `app.coordinator.on` for co-op with other things in the application, make sure to clean the listener
 * up in the view's `teardown` event.
 * 2. there are no `on<event>` shortcut functions for listeners in a view. use `.on`/`.once` and `options.events` to
 * register them instead.
 *
 *
 * Hardcode
 * --------
 * 1. templates must be named `*.mst.html`
 *
 *
 * @author Tim Lauv <bluekvirus@gmail.com>
 * @created 2015.04.27
 */
(function(_, $, app, Mustache){
	app.ve = {name: 'Basic', _tplSuffix: '.mst.html'};

	//--------------------------------View class definition---------------------------------
	//.template, .$el, .data, init() .render(e), .teardown(e), .events, .once/on/off/trigger()
	//constructor (logic-free)
	var View = function(options){
		this._options = options || {};

		//optional
		this.$el = this._options.el && $(this._options.el);
		this.$el = this._options.$el || this.$el;
		this.data = this._options.data || this.data;
		this.init = this._options.init || this._options.initialize || this.init;
		this.events = this._options.events || this.events;
		this.template = this._options.template || this.template;

		//extension point
		this.init(this._options);
		if(this.$el) this.render();
	};
	//member methods
	_.extend(View.prototype, {
		init: _.noop,

		render: function(data, $el){

			//check the template first!
			if(!this.template) app.throw('View definition requires a template!');
			var tpl = app.templates[this.template] || app.templates[this.template + app.ve._tplSuffix] || this.template;

			//sanitize params
			if(data instanceof jQuery){
				$el = data;
				data = undefined;
			}

			this.$el = $el || this.$el;
			this.data = data || this.data;

			var content = Mustache.render(tpl, this.data);

			if(this.$el) {
				//teardown previous view if template is different.
				var meta = this.$el.data();
				if(!meta) app.throw('Invalid $el upon ' + (this._name || 'view') + '.render(), check your el selector...');
				if(meta.view && (meta.view.template !== this.template))
					meta.view.teardown();

				//re-render but not registering the listeners again.
				this.$el.html(content);
				this.$el.data('view', this);
				if(!this.$el.data('_events_')) {
					//format <e> <selectors>, instead of <e1> <e2> ...
					_.each(this.events, function(fn, namenselector){
						if(_.isString(fn)) fn = this[fn];
						var tmp = _.compact(namenselector.split(' '));
						name = tmp.shift();
						if(_.size(tmp))
							this.$el.on(name, tmp.join(' '), {view: this.$el.data('view')}, fn);
						else
							this.$el.on(name, {view: this.$el.data('view')}, fn);
					}, this);

					this.$el.data('_events_', true);
				}
			}
			else return content;

			this.trigger('render');
			return this;
		},

		teardown: function(){
			if(this.$el){
				this.$el.removeData('_events_', 'view');
				this.$el.empty();
				this.trigger('teardown');
				this.off();
			}
		},

		//dynamic instance events support .once, .trigger
		//use options.events for easy .on listener registration.
		once: function(){
			if(this.$el) {
				this.$el.one.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		on: function(){
			if(this.$el) {
				this.$el.on.apply(this.$el, arguments);
				this.$el.data('_events_', true);
			}
		},

		off: function(){
			if(this.$el) {
				this.$el.off.apply(this.$el, arguments);
			}
		},

		trigger: function(){
			if(this.$el) {
				//note that we use triggerHandler instead of trigger to avoid custom event bubbling
				this.$el.triggerHandler.apply(this.$el, arguments);
			}
		},

		$trigger: function(){
			if(this.$el) {
				//allow event bubbling
				this.$el.trigger.apply(this.$el, arguments);
			}
		}
	});
	//static methods
	_.extend(View, {
		//class inheritance
		extend: function(configure, statics){
			var A = this.prototype.constructor;

			var B = function(){
				A.apply(this, arguments); //instead of A.call(this, arg1, arg2, ...)
			};

			B.prototype = new A(); //logic-free constructor
			_.extend(B.prototype, configure);
			_.extend(B, A, statics);
			//note that `prototype` and `constructor` are non-enumerable, thus won't be copied by _.extend()

			B.prototype.constructor = B;

			return B;
		}
	});

	//-----------------hooks into app infrastructure-------------------
	//convert templates into components
	app.coordinator.on('app.load', function(){

		_.each(app.templates, function(tpl, filename){
			var name = app.tplNameToCompName(filename, app.ve._tplSuffix);
			app.ve.component(name, {
				template: filename
			});

			app.debug('component registered:', name);
		});

		app.coordinator.trigger('app.loaded');
	});

	//----------------apis enhancement to app-------------------------
	app.ve.view = function(options){
		return new View(options);
	};

	app.ve.components = {};
	app.ve.component = function(name, configure){
		if(app.ve.components[name]) {
			//override
			app.ve.components[name] = app.ve.components[name].extend(configure);
		} else
			//register
			app.ve.components[name] = View.extend(_.extend({_name: name}, configure));
		return app.ve.components[name];
	};

		//internal worker for ve.inject (single target, cb(err, result))
	function _inject (options, cb){
		if(!app.isAMDEnabled()) app.throw('AMD is not enabled, use task:dance before ve.inject()');
		if(_.isString(options))
			options = {path: options};
		if(_.isFunction(options)){
			cb = options;
			options = {};
		}
		options = _.extend({
			baseURL: 'vanilla/',
			tplOnly: false,
			forceName: ''
		}, options);
		//allow :static in option.path to indicate tplOnly
		if(_.endsWith(options.path, ':static')){
			options.tplOnly = true;
			options.path = options.path.replace(/:static$/, '');
		}
		var compName = options.forceName?options.forceName:app.tplNameToCompName(options.path);
		var tplTarget = _.endsWith(options.path, '/')?[options.baseURL, options.path, 'index', app.ve._tplSuffix].join(''):[options.baseURL, options.path, app.ve._tplSuffix].join(''),
		jsTarget = tplTarget.replace(app.ve._tplSuffix, '');
		var targets = ['text!' + tplTarget];
		if(!options.tplOnly) targets.push(jsTarget);
		//don't use define here... the cb will never gets invoked. (until what's define()-ed gets required)
		require(targets, function(tpl, js){
			js = js || {};
			//as success cb
			cb(null, app.ve.component(compName, _.extend(js, {template: tpl})));
		}, cb);//as error cb
	}
	//dynamically inject js + html to make a View or multiple View(s)
	app.ve.inject = function (options, cb){
		if(_.isArray(options)){
			app.coordinator.async.map(options, _inject, cb);
		} else {
			_inject(options, cb);
		}
	};

})(_, jQuery, Application, Mustache);<|endoftext|>


<commit_before>angular.module('jwtAuth').run(['gettextCatalog', function (gettextCatalog) {
/* jshint -W100 */
    gettextCatalog.setStrings('es_AR', {"Actions":"Acciones","Add":"Agregar","Add new record":"Agregar un nuevo registro","Check all rows":"Seleccionar todas las filas","Delete":"Eliminar","Delete record":"Eliminar registro","Delete selected records":"Eliminar los registros seleccionados","Edit record":"Editar registro","entries":"registros","Field":"Campo","NO DATA FOUND":"Sin resultados","of":"de","Page size":"Mostrar","Refresh":"Actualizar","Search":"Buscar","Search for":"Buscar por","Select a field":"Seleccione un campo","Select a value":"Seleccione un valor","Selected rows":"Filas seleccionadas","Server response":"Respuesta del servidor","Showing":"Mostrando","Sort asc.":"Orden asc.","Sort desc.":"Orden desc.","to":"al","Uncheck all rows":"Quitar selección"});
/* jshint +W100 */
}]);<commit_msg>Update translation<commit_after>angular.module('jwtAuth').run(['gettextCatalog', function(gettextCatalog) {
    /* jshint -W100 */
    gettextCatalog.setStrings('es_AR', {
        'Actions'                : 'Acciones',
        'Add'                    : 'Agregar',
        'Add new record'         : 'Agregar un nuevo registro',
        'Check all rows'         : 'Seleccionar todas las filas',
        'Delete'                 : 'Eliminar',
        'Delete record'          : 'Eliminar registro',
        'Delete selected records': 'Eliminar los registros seleccionados',
        'Edit record'            : 'Editar registro',
        'entries'                : 'registros',
        'Field'                  : 'Campo',
        'NO DATA FOUND'          : 'Sin resultados',
        'of'                     : 'de',
        'Page size'              : 'Mostrar',
        'Refresh'                : 'Actualizar',
        'Search'                 : 'Buscar',
        'Search for'             : 'Buscar por',
        'Select a field'         : 'Seleccione un campo',
        'Select a value'         : 'Seleccione un valor',
        'Selected rows'          : 'Filas seleccionadas',
        'Server response'        : 'Respuesta del servidor',
        'Showing'                : 'Mostrando',
        'Sort asc.'              : 'Orden asc.',
        'Sort desc.'             : 'Orden desc.',
        'to'                     : 'al',
        'Uncheck all rows'       : 'Quitar selección'
    });
    /* jshint +W100 */
}]);
<|endoftext|>


<commit_before>// load the default config generator.
const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js');
module.exports = (baseConfig, env) => {
  const config = genDefaultConfig(baseConfig, env);
  // Extend it as you need.
  // For example, add typescript loader:
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    use: [
        "babel-loader",
        {
            loader: "awesome-typescript-loader",
        },
    ]
  });
  config.module.rules.push({
    test: /\.scss$/,
    use: [
        "style-loader",
        "css-loader",
        "sass-loader",
    ]
  });
  config.devtool = "eval-source-map";
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};<commit_msg>Automatically include prefix in classes<commit_after>// load the default config generator.
const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js');
module.exports = (baseConfig, env) => {
  const config = genDefaultConfig(baseConfig, env);
  // Extend it as you need.
  // For example, add typescript loader:
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    use: [
        "babel-loader",
        {
            loader: "awesome-typescript-loader",
        },
    ]
  });
  config.module.rules.push({
    test: /\.scss$/,
    use: [
        "style-loader",
        {
          loader: "css-loader",
          options: {
            modules: true,
            localIdentName: "--react-data-table--[local]"
          },
        },
        "sass-loader",
    ]
  });
  config.devtool = "eval-source-map";
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};<|endoftext|>


<commit_before>//
// Copyright (c) 2008-2009 rPath, Inc.
// All rights reserved
//

function updateCurrentStep(stepNumber, completed, completedMsg) {
    var step = 'step' + stepNumber;
    var currentFound = false;

    var liEl = $('statusList');
    forEach (liEl.getElementsByTagName('li'), function (e) {
        if (e.id.indexOf(step) >= 0) {
            currentFound = true;
            if (completed) {
                setElementClass(e, 'completedState');
            }
            else {
                setElementClass(e, 'currentState');
            }
        }
        else {
            if (!currentFound && stepNumber > 0)  {
                setElementClass(e, 'completedState');
            }
        }
    });

    if (completed) {
        var msg = completedMsg || '';
        if (msg.length > 0) {
            $('completedMsg').innerHTML = errorMsg;
            showElement('completedMsg');
        }
        removeElementClass('continue_button', 'off');
        setNodeAttribute('continue_button', 'href', 'javascript:button_submit(document.page_form)');
    }
}

function getUpdatedStatus() {

    function _callback(req) {
        var newStep = req['currentStep'];
        var statusCode = req['status'];
        var completed;
        var errors;
        if (statusCode == TASK_RUNNING ||
            statusCode == TASK_SCHEDULED ||
            statusCode == TASK_PENDING ||
            statusCode == TASK_PREVENTED) {
            callLater(2, getUpdatedStatus);
            completed = false;
        }
        else {
            completed = true;
            if (statusCode != TASK_SUCCESS) {
                errors = req['statusMsg'];
            }
        }
        updateCurrentStep(newStep, completed, errors);
    }

    function _callbackErr() {
        callLater(2, getUpdatedStatus);
    }

    postRequest('getFirstTimeSetupStatus', null, null,
            _callback, _callbackErr, false);
}

addLoadEvent(getUpdatedStatus);

<commit_msg>Shut up the 'working' message on the first time status page<commit_after>//
// Copyright (c) 2008-2009 rPath, Inc.
// All rights reserved
//

function updateCurrentStep(stepNumber, completed, completedMsg) {
    var step = 'step' + stepNumber;
    var currentFound = false;

    var liEl = $('statusList');
    forEach (liEl.getElementsByTagName('li'), function (e) {
        if (e.id.indexOf(step) >= 0) {
            currentFound = true;
            if (completed) {
                setElementClass(e, 'completedState');
            }
            else {
                setElementClass(e, 'currentState');
            }
        }
        else {
            if (!currentFound && stepNumber > 0)  {
                setElementClass(e, 'completedState');
            }
        }
    });

    if (completed) {
        var msg = completedMsg || '';
        if (msg.length > 0) {
            $('completedMsg').innerHTML = errorMsg;
            showElement('completedMsg');
        }
        removeElementClass('continue_button', 'off');
        setNodeAttribute('continue_button', 'href', 'javascript:button_submit(document.page_form)');
    }
}

function getUpdatedStatus() {

    function _callback(req) {
        var newStep = req['currentStep'];
        var statusCode = req['status'];
        var completed;
        var errors;
        if (statusCode == TASK_RUNNING ||
            statusCode == TASK_SCHEDULED ||
            statusCode == TASK_PENDING ||
            statusCode == TASK_PREVENTED) {
            callLater(2, getUpdatedStatus);
            completed = false;
        }
        else {
            completed = true;
            if (statusCode != TASK_SUCCESS) {
                errors = req['statusMsg'];
            }
        }
        updateCurrentStep(newStep, completed, errors);
    }

    function _callbackErr() {
        callLater(2, getUpdatedStatus);
    }

    postRequest('getFirstTimeSetupStatus', null, null,
            _callback, _callbackErr, false);
}

// Neuter the postRequest's WORKING message box for these requests; it's
// glitchy and redundant
post.showWorking = function(req) { void(0); }

addLoadEvent(getUpdatedStatus);

<|endoftext|>


<commit_before>var map = require('map-stream');

/**
 *
 * 排除 _ 开头的参数
 * @returns {Stream}
 */
module.exports = function (nextStream) {
  var stream = map(function (data, fn) {

      for(var key in data.data ){
            if(/_.+/.test(key)){
                delete data.data[key];
            }
      }

      fn(null, data);
  });
  return stream;
};<commit_msg>回滚代码， 并修复正则<commit_after>
/**
 *
 * 排除 _ 开头的参数
 * @returns {Stream}
 */
module.exports = function (nextStream) {
    return {
        process : function (data){
            for(var key in data.data ){
                if(/^_.+/.test(key)){
                    delete data.data[key];
                }
            }

        }
    }
};<|endoftext|>


<commit_before>process.env.NODE_ENV = 'test'

// The following allows you to require files independent of
// the location of your test file.
// Example:
//  var User = require(__server + '/models/user.js')
//
global.__server = __dirname + '/../server'
global.__client = __dirname + '/../client'

//
// Assertions
//
var chai = require('chai')
// Option 1: Make the `expect` function available in every test file
global.expect = chai.expect
// Option 2: Make everything should-able
// global.should = chai.should()

//
// Helper Functions
//
// This is the object you can attach any helper functions used across
// several test files.
global.TestHelper = {}

//
// Mock apps for API testing
//
var express = require('express')

TestHelper.createApp = function (loader) {
  var app = express()
  app.use(require('body-parser').json())

  app.testReady = function () {
    // Log all errors
    app.use(function (err, req, res, next) {
      console.error("==Error==")
      console.error("   " + err.stack)
      next(err)
    })
  }
  return app
}

//
// Mocha "helpers" to support coroutines tests
//
var Bluebird = require('bluebird')

global.before_ = function (f) { before ( Bluebird.coroutine(f) ) }
global.beforeEach_ = function (f) { beforeEach ( Bluebird.coroutine(f) ) }
global.it_ = function (description, f) { it ( description, f && Bluebird.coroutine(f) ) }
global.xit_ = function (description, f) { xit ( description, f ) }
global.it_.only = function (description, f) { it.only( description, Bluebird.coroutine(f) ) }
<commit_msg>Add test folder ref<commit_after>process.env.NODE_ENV = 'test'

// The following allows you to require files independent of
// the location of your test file.
// Example:
//  var User = require(__server + '/models/user.js')
//
global.__test   = __dirname
global.__server = __dirname + '/../server'
global.__client = __dirname + '/../client'

//
// Assertions
//
var chai = require('chai')
// Option 1: Make the `expect` function available in every test file
global.expect = chai.expect
// Option 2: Make everything should-able
// global.should = chai.should()

//
// Helper Functions
//
// This is the object you can attach any helper functions used across
// several test files.
global.TestHelper = {}

//
// Mock apps for API testing
//
var express = require('express')

TestHelper.createApp = function (loader) {
  var app = express()
  app.use(require('body-parser').json())

  app.testReady = function () {
    // Log all errors
    app.use(function (err, req, res, next) {
      console.error("==Error==")
      console.error("   " + err.stack)
      next(err)
    })
  }
  return app
}

//
// Mocha "helpers" to support coroutines tests
//
var Bluebird = require('bluebird')

global.before_ = function (f) { before ( Bluebird.coroutine(f) ) }
global.beforeEach_ = function (f) { beforeEach ( Bluebird.coroutine(f) ) }
global.it_ = function (description, f) { it ( description, f && Bluebird.coroutine(f) ) }
global.xit_ = function (description, f) { xit ( description, f ) }
global.it_.only = function (description, f) { it.only( description, Bluebird.coroutine(f) ) }
<|endoftext|>


<commit_before>mapbox.markers.layer = function() {

    var m = {},
        // external list of geojson features
        features = [],
        // internal list of markers
        markers = [],
        // internal list of callbacks
        callbackManager = new MM.CallbackManager(m, ['drawn', 'markeradded']),
        // the absolute position of the parent element
        position = null,
        // a factory function for creating DOM elements out of
        // GeoJSON objects
        factory = mapbox.markers.simplestyle_factory,
        // a sorter function for sorting GeoJSON objects
        // in the DOM
        sorter = function(a, b) {
            return b.geometry.coordinates[1] -
              a.geometry.coordinates[1];
        },
        // a list of urls from which features can be loaded.
        // these can be templated with {z}, {x}, and {y}
        urls,
        // map bounds
        left = null,
        right = null,
        // a function that filters points
        filter = function() {
            return true;
        },
        _seq = 0,
        keyfn = function() {
            return ++_seq;
        },
        index = {};

    // The parent DOM element
    m.parent = document.createElement('div');
    m.parent.style.cssText = 'position: absolute; top: 0px;' +
        'left:0px; width:100%; height:100%; margin:0; padding:0; z-index:0;pointer-events:none;';
    m.name = 'markers';

    // reposition a single marker element
    function reposition(marker) {
        // remember the tile coordinate so we don't have to reproject every time
        if (!marker.coord) marker.coord = m.map.locationCoordinate(marker.location);
        var pos = m.map.coordinatePoint(marker.coord);
        var pos_loc, new_pos;

        // If this point has wound around the world, adjust its position
        // to the new, onscreen location
        if (pos.x < 0) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon += Math.ceil((left.lon - marker.location.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x < m.map.dimensions.x) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        } else if (pos.x > m.map.dimensions.x) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon -= Math.ceil((marker.location.lon - right.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x > 0) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        }

        pos.scale = 1;
        pos.width = pos.height = 0;
        MM.moveElement(marker.element, pos);
    }

    // Adding and removing callbacks is mainly a way to enable mmg_interaction to operate.
    // I think there are better ways to do this, by, for instance, having mmg be able to
    // register 'binders' to markers, but this is backwards-compatible and equivalent
    // externally.
    m.addCallback = function(event, callback) {
        callbackManager.addCallback(event, callback);
        return m;
    };

    m.removeCallback = function(event, callback) {
        callbackManager.removeCallback(event, callback);
        return m;
    };

    // Draw this layer - reposition all markers on the div. This requires
    // the markers library to be attached to a map, and will noop otherwise.
    m.draw = function() {
        if (!m.map) return;
        left = m.map.pointLocation(new MM.Point(0, 0));
        right = m.map.pointLocation(new MM.Point(m.map.dimensions.x, 0));
        callbackManager.dispatchCallback('drawn', m);
        for (var i = 0; i < markers.length; i++) {
            reposition(markers[i]);
        }
    };

    // Add a fully-formed marker to the layer. This fires a `markeradded` event.
    // This does not require the map element t be attached.
    m.add = function(marker) {
        if (!marker || !marker.element) return null;
        m.parent.appendChild(marker.element);
        markers.push(marker);
        callbackManager.dispatchCallback('markeradded', marker);
        return marker;
    };

    // Remove a fully-formed marker - which must be the same exact marker
    // object as in the markers array - from the layer.
    m.remove = function(marker) {
        if (!marker) return null;
        m.parent.removeChild(marker.element);
        for (var i = 0; i < markers.length; i++) {
            if (markers[i] === marker) {
                markers.splice(i, 1);
                return marker;
            }
        }
        return marker;
    };

    m.markers = function(x) {
        if (!arguments.length) return markers;
    };

    // Add a GeoJSON feature to the markers layer.
    m.add_feature = function(x) {
        return m.features(m.features().concat([x]));
    };

    m.sort = function(x) {
        if (!arguments.length) return sorter;
        sorter = x;
        return m;
    };

    // Public data interface
    m.features = function(x) {
        // Return features
        if (!arguments.length) return features;

        // Set features
        if (!x) x = [];
        features = x.slice();

        features.sort(sorter);

        for (var j = 0; j < markers.length; j++) {
            markers[j].touch = false;
        }

        for (var i = 0; i < features.length; i++) {
            if (filter(features[i])) {
                var id = keyfn(features[i]);
                if (index[id]) {
                    // marker is already on the map, needs to be moved or rebuilt
                    index[id].location = new MM.Location(
                        features[i].geometry.coordinates[1],
                        features[i].geometry.coordinates[0]);
                    index[id].coord = null;
                    reposition(index[id]);
                } else {
                    // marker needs to be added to the map
                    index[id] = m.add({
                        element: factory(features[i]),
                        location: new MM.Location(
                            features[i].geometry.coordinates[1],
                            features[i].geometry.coordinates[0]),
                        data: features[i]
                    });
                }
                if (index[id]) index[id].touch = true;
            }
        }

        for (var k = markers.length - 1; k >= 0; k--) {
            if (markers[k].touch === false) {
                m.remove(markers[k]);
            }
        }

        if (m.map && m.map.coordinate) m.map.draw();

        return m;
    };

    // Request features from a URL - either a local URL or a JSONP call.
    // Expects GeoJSON-formatted features.
    m.url = function(x, callback) {
        if (!arguments.length) return urls;
        if (typeof reqwest === 'undefined') throw 'reqwest is required for url loading';
        if (typeof x === 'string') x = [x];

        urls = x;
        function add_features(err, x) {
            if (err && callback) return callback(err);
            if (x && x.features) m.features(x.features);
            if (callback) callback(err, x.features, m);
        }

        reqwest((urls[0].match(/geojsonp$/)) ? {
            url: urls[0] + (~urls[0].indexOf('?') ? '&' : '?') + 'callback=grid',
            type: 'jsonp',
            jsonpCallback: 'callback',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        } : {
            url: urls[0],
            type: 'json',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        });
        return m;
    };

    m.id = function(x, callback) {
        return m.url('http://a.tiles.mapbox.com/v3/' + x + '/markers.geojsonp', callback);
    };

    m.csv = function(x) {
        return m.features(mapbox.markers.csv_to_geojson(x));
    };

    m.extent = function() {
        var ext = [{
            lat: Infinity,
            lon: Infinity
        }, {
            lat: -Infinity,
            lon: -Infinity
        }];
        var ft = m.features();
        for (var i = 0; i < ft.length; i++) {
            var coords = ft[i].geometry.coordinates;
            if (coords[0] < ext[0].lon) ext[0].lon = coords[0];
            if (coords[1] < ext[0].lat) ext[0].lat = coords[1];
            if (coords[0] > ext[1].lon) ext[1].lon = coords[0];
            if (coords[1] > ext[1].lat) ext[1].lat = coords[1];
        }
        return ext;
    };

    m.key = function(x) {
        if (!arguments.length) return keyfn;
        if (x === null) {
            keyfn = function() { return ++_seq; };
        } else {
            keyfn = x;
        }
        return m;
    };

    // Factory interface
    m.factory = function(x) {
        if (!arguments.length) return factory;
        factory = x;
        // re-render all features
        m.features(m.features());
        return m;
    };

    m.filter = function(x) {
        if (!arguments.length) return filter;
        filter = x;
        // Setting a filter re-sets the features into a new array.
        // This does _not_ change the actual output of .features()
        m.features(m.features());
        return m;
    };

    m.destroy = function() {
        if (m.parent.parentNode) {
            m.parent.parentNode.removeChild(m.parent);
        }
    };

    // Get or set this layer's name
    m.named = function(x) {
        if (!arguments.length) return m.name;
        m.name = x;
        return m;
    };

    m.enabled = true;

    m.enable = function() {
        this.enabled = true;
        this.parent.style.display = '';
        return m;
    };

    m.disable = function() {
        this.enabled = false;
        this.parent.style.display = 'none';
        return m;
    };

    return m;
};

mmg = mapbox.markers.layer; // Backwards compatibility
<commit_msg>Makes check for the presence of x and x.features consistent. Fixes an error in IE9, where the x object is undefined in case the markers URL yields a geojson object with an empty features array.<commit_after>mapbox.markers.layer = function() {

    var m = {},
        // external list of geojson features
        features = [],
        // internal list of markers
        markers = [],
        // internal list of callbacks
        callbackManager = new MM.CallbackManager(m, ['drawn', 'markeradded']),
        // the absolute position of the parent element
        position = null,
        // a factory function for creating DOM elements out of
        // GeoJSON objects
        factory = mapbox.markers.simplestyle_factory,
        // a sorter function for sorting GeoJSON objects
        // in the DOM
        sorter = function(a, b) {
            return b.geometry.coordinates[1] -
              a.geometry.coordinates[1];
        },
        // a list of urls from which features can be loaded.
        // these can be templated with {z}, {x}, and {y}
        urls,
        // map bounds
        left = null,
        right = null,
        // a function that filters points
        filter = function() {
            return true;
        },
        _seq = 0,
        keyfn = function() {
            return ++_seq;
        },
        index = {};

    // The parent DOM element
    m.parent = document.createElement('div');
    m.parent.style.cssText = 'position: absolute; top: 0px;' +
        'left:0px; width:100%; height:100%; margin:0; padding:0; z-index:0;pointer-events:none;';
    m.name = 'markers';

    // reposition a single marker element
    function reposition(marker) {
        // remember the tile coordinate so we don't have to reproject every time
        if (!marker.coord) marker.coord = m.map.locationCoordinate(marker.location);
        var pos = m.map.coordinatePoint(marker.coord);
        var pos_loc, new_pos;

        // If this point has wound around the world, adjust its position
        // to the new, onscreen location
        if (pos.x < 0) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon += Math.ceil((left.lon - marker.location.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x < m.map.dimensions.x) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        } else if (pos.x > m.map.dimensions.x) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon -= Math.ceil((marker.location.lon - right.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x > 0) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        }

        pos.scale = 1;
        pos.width = pos.height = 0;
        MM.moveElement(marker.element, pos);
    }

    // Adding and removing callbacks is mainly a way to enable mmg_interaction to operate.
    // I think there are better ways to do this, by, for instance, having mmg be able to
    // register 'binders' to markers, but this is backwards-compatible and equivalent
    // externally.
    m.addCallback = function(event, callback) {
        callbackManager.addCallback(event, callback);
        return m;
    };

    m.removeCallback = function(event, callback) {
        callbackManager.removeCallback(event, callback);
        return m;
    };

    // Draw this layer - reposition all markers on the div. This requires
    // the markers library to be attached to a map, and will noop otherwise.
    m.draw = function() {
        if (!m.map) return;
        left = m.map.pointLocation(new MM.Point(0, 0));
        right = m.map.pointLocation(new MM.Point(m.map.dimensions.x, 0));
        callbackManager.dispatchCallback('drawn', m);
        for (var i = 0; i < markers.length; i++) {
            reposition(markers[i]);
        }
    };

    // Add a fully-formed marker to the layer. This fires a `markeradded` event.
    // This does not require the map element t be attached.
    m.add = function(marker) {
        if (!marker || !marker.element) return null;
        m.parent.appendChild(marker.element);
        markers.push(marker);
        callbackManager.dispatchCallback('markeradded', marker);
        return marker;
    };

    // Remove a fully-formed marker - which must be the same exact marker
    // object as in the markers array - from the layer.
    m.remove = function(marker) {
        if (!marker) return null;
        m.parent.removeChild(marker.element);
        for (var i = 0; i < markers.length; i++) {
            if (markers[i] === marker) {
                markers.splice(i, 1);
                return marker;
            }
        }
        return marker;
    };

    m.markers = function(x) {
        if (!arguments.length) return markers;
    };

    // Add a GeoJSON feature to the markers layer.
    m.add_feature = function(x) {
        return m.features(m.features().concat([x]));
    };

    m.sort = function(x) {
        if (!arguments.length) return sorter;
        sorter = x;
        return m;
    };

    // Public data interface
    m.features = function(x) {
        // Return features
        if (!arguments.length) return features;

        // Set features
        if (!x) x = [];
        features = x.slice();

        features.sort(sorter);

        for (var j = 0; j < markers.length; j++) {
            markers[j].touch = false;
        }

        for (var i = 0; i < features.length; i++) {
            if (filter(features[i])) {
                var id = keyfn(features[i]);
                if (index[id]) {
                    // marker is already on the map, needs to be moved or rebuilt
                    index[id].location = new MM.Location(
                        features[i].geometry.coordinates[1],
                        features[i].geometry.coordinates[0]);
                    index[id].coord = null;
                    reposition(index[id]);
                } else {
                    // marker needs to be added to the map
                    index[id] = m.add({
                        element: factory(features[i]),
                        location: new MM.Location(
                            features[i].geometry.coordinates[1],
                            features[i].geometry.coordinates[0]),
                        data: features[i]
                    });
                }
                if (index[id]) index[id].touch = true;
            }
        }

        for (var k = markers.length - 1; k >= 0; k--) {
            if (markers[k].touch === false) {
                m.remove(markers[k]);
            }
        }

        if (m.map && m.map.coordinate) m.map.draw();

        return m;
    };

    // Request features from a URL - either a local URL or a JSONP call.
    // Expects GeoJSON-formatted features.
    m.url = function(x, callback) {
        if (!arguments.length) return urls;
        if (typeof reqwest === 'undefined') throw 'reqwest is required for url loading';
        if (typeof x === 'string') x = [x];

        urls = x;
        function add_features(err, x) {
            if (err && callback) return callback(err);
            var features = x && x.features ? x.features : null;
            if (features) m.features(features);
            if (callback) callback(err, features, m);
        }

        reqwest((urls[0].match(/geojsonp$/)) ? {
            url: urls[0] + (~urls[0].indexOf('?') ? '&' : '?') + 'callback=grid',
            type: 'jsonp',
            jsonpCallback: 'callback',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        } : {
            url: urls[0],
            type: 'json',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        });
        return m;
    };

    m.id = function(x, callback) {
        return m.url('http://a.tiles.mapbox.com/v3/' + x + '/markers.geojsonp', callback);
    };

    m.csv = function(x) {
        return m.features(mapbox.markers.csv_to_geojson(x));
    };

    m.extent = function() {
        var ext = [{
            lat: Infinity,
            lon: Infinity
        }, {
            lat: -Infinity,
            lon: -Infinity
        }];
        var ft = m.features();
        for (var i = 0; i < ft.length; i++) {
            var coords = ft[i].geometry.coordinates;
            if (coords[0] < ext[0].lon) ext[0].lon = coords[0];
            if (coords[1] < ext[0].lat) ext[0].lat = coords[1];
            if (coords[0] > ext[1].lon) ext[1].lon = coords[0];
            if (coords[1] > ext[1].lat) ext[1].lat = coords[1];
        }
        return ext;
    };

    m.key = function(x) {
        if (!arguments.length) return keyfn;
        if (x === null) {
            keyfn = function() { return ++_seq; };
        } else {
            keyfn = x;
        }
        return m;
    };

    // Factory interface
    m.factory = function(x) {
        if (!arguments.length) return factory;
        factory = x;
        // re-render all features
        m.features(m.features());
        return m;
    };

    m.filter = function(x) {
        if (!arguments.length) return filter;
        filter = x;
        // Setting a filter re-sets the features into a new array.
        // This does _not_ change the actual output of .features()
        m.features(m.features());
        return m;
    };

    m.destroy = function() {
        if (m.parent.parentNode) {
            m.parent.parentNode.removeChild(m.parent);
        }
    };

    // Get or set this layer's name
    m.named = function(x) {
        if (!arguments.length) return m.name;
        m.name = x;
        return m;
    };

    m.enabled = true;

    m.enable = function() {
        this.enabled = true;
        this.parent.style.display = '';
        return m;
    };

    m.disable = function() {
        this.enabled = false;
        this.parent.style.display = 'none';
        return m;
    };

    return m;
};

mmg = mapbox.markers.layer; // Backwards compatibility
<|endoftext|>


<commit_before>import uuid from 'uuid';
import React from 'react';
import { connectToStores } from 'fluxible-addons-react';
import UploadImageStore from '../stores/UploadImageStore';
import ImageStore from '../stores/ImageStore';
import selectUnsentImageFile from '../actions/selectUnsentImageFile';
import uploadImageAction from '../actions/uploadImageAction';

class GyazoUploadFormComponent extends React.Component {
  static contextTypes = {
    getStore: React.PropTypes.func.isRequired,
    executeAction: React.PropTypes.func.isRequired
  };

  static propTypes = {
    gyazoId: React.PropTypes.string.isRequired,
    id: React.PropTypes.string,
    imageFile: React.PropTypes.object,
    imageUri: React.PropTypes.string,
    readyState: React.PropTypes.string.isRequired,
    uri: React.PropTypes.string.isRequired,
    useProxy: React.PropTypes.bool.isRequired
  };

  static defaultProps = {
    gyazoId: '',
    imageFile: null,
    imageUri: null,
    readyState: 'unsent',
    uri: 'https://gyazo.com/upload.cgi',
    useProxy: true
  };

  handleSubmit(event) {
    event.preventDefault();
    let imageFile = this.props.imageFile;
    if (!(imageFile instanceof File)) {
      return false;
    }
    this.context.executeAction(uploadImageAction, {
      uri: this.props.uri,
      gyazoId: this.props.gyazoId,
      imageFile
    });
    return false;
  }

  handleChange(event) {
    event.preventDefault();
    let imageFile = (this.refs.gyazoImageData.files || [])[0];
    if (!(imageFile instanceof File)) {
      return false;
    }
    this.context.executeAction(selectUnsentImageFile, { imageFile });
    return false;
  }

  canSubmit() {
    return ['unsent', 'done'].includes(this.props.readyState);
  }

  render() {
    return (

        <form className='form-horizontal' method='post' onSubmit={::this.handleSubmit}>
          <fieldset className='card'>

                <input className='file' id='gyazo-image' name='imagedata' onChange={::this.handleChange} ref='gyazoImageData' style={{maxWidth: '100%'}} type='file'/>

              {((imageUri) => imageUri && (
                <button className='btn btn-primary' disabled={!this.canSubmit()} type='submit'>
                  {((readyState) => !this.canSubmit() && (

                  ))(this.props.readyState)}
                  {this.canSubmit() ? 'Upload' : 'Uploading...'}
                  </button>
              ))(this.props.imageUri)}

          </fieldset>
        </form>

    );
  }
}

GyazoUploadFormComponent = connectToStores(GyazoUploadFormComponent, [UploadImageStore], (context) => {
  let uploadImageStore = context.getStore(UploadImageStore);
  return {
    imageFile: uploadImageStore.getCurrentImageFile(),
    imageUri: uploadImageStore.getCurrentImageUri(),
    readyState: uploadImageStore.getCurrentReadyState()
  };
});
export default GyazoUploadFormComponent;
<commit_msg>PNG 画像以外を選択することができないように<commit_after>import uuid from 'uuid';
import React from 'react';
import { connectToStores } from 'fluxible-addons-react';
import UploadImageStore from '../stores/UploadImageStore';
import ImageStore from '../stores/ImageStore';
import selectUnsentImageFile from '../actions/selectUnsentImageFile';
import uploadImageAction from '../actions/uploadImageAction';

class GyazoUploadFormComponent extends React.Component {
  static contextTypes = {
    getStore: React.PropTypes.func.isRequired,
    executeAction: React.PropTypes.func.isRequired
  };

  static propTypes = {
    gyazoId: React.PropTypes.string.isRequired,
    id: React.PropTypes.string,
    imageFile: React.PropTypes.object,
    imageUri: React.PropTypes.string,
    readyState: React.PropTypes.string.isRequired,
    uri: React.PropTypes.string.isRequired,
    useProxy: React.PropTypes.bool.isRequired
  };

  static defaultProps = {
    gyazoId: '',
    imageFile: null,
    imageUri: null,
    readyState: 'unsent',
    uri: 'https://gyazo.com/upload.cgi',
    useProxy: true
  };

  handleSubmit(event) {
    event.preventDefault();
    let imageFile = this.props.imageFile;
    if (!(imageFile instanceof File)) {
      return false;
    }
    this.context.executeAction(uploadImageAction, {
      uri: this.props.uri,
      gyazoId: this.props.gyazoId,
      imageFile
    });
    return false;
  }

  handleChange(event) {
    event.preventDefault();
    let imageFile = (this.refs.gyazoImageData.files || [])[0];
    if (!(imageFile instanceof File)) {
      return false;
    }
    this.context.executeAction(selectUnsentImageFile, { imageFile });
    return false;
  }

  canSubmit() {
    return ['unsent', 'done'].includes(this.props.readyState);
  }

  render() {
    return (

        <form className='form-horizontal' method='post' onSubmit={::this.handleSubmit}>
          <fieldset className='card'>

                <input accept='image/png' className='file' id='gyazo-image' name='imagedata' onChange={::this.handleChange} ref='gyazoImageData' style={{maxWidth: '100%'}} type='file'/>

              {((imageUri) => imageUri && (
                <button className='btn btn-primary' disabled={!this.canSubmit()} type='submit'>
                  {((readyState) => !this.canSubmit() && (

                  ))(this.props.readyState)}
                  {this.canSubmit() ? 'Upload' : 'Uploading...'}
                  </button>
              ))(this.props.imageUri)}

          </fieldset>
        </form>

    );
  }
}

GyazoUploadFormComponent = connectToStores(GyazoUploadFormComponent, [UploadImageStore], (context) => {
  let uploadImageStore = context.getStore(UploadImageStore);
  return {
    imageFile: uploadImageStore.getCurrentImageFile(),
    imageUri: uploadImageStore.getCurrentImageUri(),
    readyState: uploadImageStore.getCurrentReadyState()
  };
});
export default GyazoUploadFormComponent;
<|endoftext|>