<commit_before>var Formsy = require('./../src/main.js');

describe('Element', function() {

  it('should return passed and setValue() value when using getValue()', function () {

    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo"/>
      </Formsy.Form>
    );

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    expect(input.getDOMNode().value).toBe('foo');
    TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
    expect(input.getDOMNode().value).toBe('foobar');

  });

  it('should return true or false when calling hasValue() depending on value existance', function () {

    var reset = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        reset = this.resetValue;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo"/>
      </Formsy.Form>
    );

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    reset();
    expect(input.getDOMNode().value).toBe('');

  });

  it('should return error message passed when calling getErrorMessage()', function () {

    var getErrorMessage = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        getErrorMessage = this.getErrorMessage;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
      </Formsy.Form>
    );

    expect(getErrorMessage()).toBe('Has to be email');

  });

  it('should return server error message when calling getErrorMessage()', function (done) {

    jasmine.Ajax.install();

    var getErrorMessage = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        getErrorMessage = this.getErrorMessage;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
      </Formsy.Form>
    );

    var form = TestUtils.Simulate.submit(form.getDOMNode());

    jasmine.Ajax.requests.mostRecent().respondWith({
      status: 500,
      contentType: 'application/json',
      responseText: '{"foo": "bar"}'
    })

    setTimeout(function () {
      expect(getErrorMessage()).toBe('bar');
      jasmine.Ajax.uninstall();
      done();
    }, 0);

  });

  it('should return true or false when calling isValid() depending on valid state', function () {

    var isValid = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isValid = this.isValid;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail"/>
      </Formsy.Form>
    );

    expect(isValid()).toBe(false);
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
    expect(isValid()).toBe(true);

  });

  it('should return true or false when calling isRequired() depending on passed required attribute', function () {

    var isRequireds = [];
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isRequireds.push(this.isRequired);
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo"/>
        <TestInput name="foo" value="foo" required/>
      </Formsy.Form>
    );

    expect(isRequireds[0]()).toBe(false);
    expect(isRequireds[1]()).toBe(true);

  });

  it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () {

    var showRequireds = [];
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        showRequireds.push(this.showRequired);
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="A" value="foo"/>
        <TestInput name="B" value="" required/>
        <TestInput name="C" value=""/>
      </Formsy.Form>
    );

    expect(showRequireds[0]()).toBe(false);
    expect(showRequireds[1]()).toBe(true);
    expect(showRequireds[2]()).toBe(false);

  });

  it('should return true or false when calling showError() depending on value is invalid or a server error has arrived, or not', function (done) {

    var showError = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        showError = this.showError;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail" validationError="This is not an email"/>
      </Formsy.Form>
    );

    expect(showError()).toBe(true);

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
    expect(showError()).toBe(false);

    jasmine.Ajax.install();
    TestUtils.Simulate.submit(form.getDOMNode());
    jasmine.Ajax.requests.mostRecent().respondWith({
      status: 500,
      responseType: 'application/json',
      responseText: '{"foo": "Email already exists"}'
    });
    setTimeout(function () {
      expect(showError()).toBe(true);
      jasmine.Ajax.uninstall();
      done();
    }, 0);
  });

  it('should return true or false when calling isPrestine() depending on input has been "touched" or not', function () {

    var isPristine = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isPristine = this.isPristine;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="A" value="foo"/>
      </Formsy.Form>
    );

    expect(isPristine()).toBe(true);
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo'}});
    expect(isPristine()).toBe(false);

  });

it('should allow an undefined value to be updated to a value', function (done) {
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      render: function () {
        return <input value={this.getValue()}/>
      }
    });
    var TestForm = React.createClass({
      getInitialState: function () {
        return {value: undefined};
      },
      changeValue: function () {
        this.setState({
          value: 'foo'
        });
      },
      render: function () {
        return (
          <Formsy.Form url="/users">
            <TestInput name="A" value={this.state.value}/>
          </Formsy.Form>
        );
      }
    });
    var form = TestUtils.renderIntoDocument(
      <TestForm/>
    );

    form.changeValue();
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    setTimeout(function () {
      expect(input.getDOMNode().value).toBe('foo');
      done();
    }, 0);
  });

it('should be able to dynamically change validations', function (done) {

    var isInvalid = false;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      render: function () {
        return <input value={this.getValue()}/>
      }
    });
    var TestForm = React.createClass({
      getInitialState: function () {
        return {value: 'foo@bar.com', validations: 'isEmail'};
      },
      changeValidations: function () {
        this.setState({
          validations: 'equals:foo'
        });
      },
      setInvalid: function () {
        console.log('Running it!');
        isInvalid = true;
      },
      render: function () {
        return (
          <Formsy.Form url="/users" onInvalid={this.setInvalid}>
            <TestInput name="A" validations={this.state.validations} value={this.state.value}/>
          </Formsy.Form>
        );
      }
    });
    var form = TestUtils.renderIntoDocument(
      <TestForm/>
    );

    form.changeValidations();
    setTimeout(function () {
      expect(isInvalid).toBe(true);
      done();
    }, 0);
  });

});
<commit_msg>Element spec: Fix typo in spec description<commit_after>var Formsy = require('./../src/main.js');

describe('Element', function() {

  it('should return passed and setValue() value when using getValue()', function () {

    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo"/>
      </Formsy.Form>
    );

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    expect(input.getDOMNode().value).toBe('foo');
    TestUtils.Simulate.change(input, {target: {value: 'foobar'}});
    expect(input.getDOMNode().value).toBe('foobar');

  });

  it('should return true or false when calling hasValue() depending on value existance', function () {

    var reset = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        reset = this.resetValue;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo"/>
      </Formsy.Form>
    );

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    reset();
    expect(input.getDOMNode().value).toBe('');

  });

  it('should return error message passed when calling getErrorMessage()', function () {

    var getErrorMessage = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        getErrorMessage = this.getErrorMessage;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form>
        <TestInput name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
      </Formsy.Form>
    );

    expect(getErrorMessage()).toBe('Has to be email');

  });

  it('should return server error message when calling getErrorMessage()', function (done) {

    jasmine.Ajax.install();

    var getErrorMessage = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        getErrorMessage = this.getErrorMessage;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail" validationError="Has to be email"/>
      </Formsy.Form>
    );

    var form = TestUtils.Simulate.submit(form.getDOMNode());

    jasmine.Ajax.requests.mostRecent().respondWith({
      status: 500,
      contentType: 'application/json',
      responseText: '{"foo": "bar"}'
    })

    setTimeout(function () {
      expect(getErrorMessage()).toBe('bar');
      jasmine.Ajax.uninstall();
      done();
    }, 0);

  });

  it('should return true or false when calling isValid() depending on valid state', function () {

    var isValid = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isValid = this.isValid;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail"/>
      </Formsy.Form>
    );

    expect(isValid()).toBe(false);
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
    expect(isValid()).toBe(true);

  });

  it('should return true or false when calling isRequired() depending on passed required attribute', function () {

    var isRequireds = [];
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isRequireds.push(this.isRequired);
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo"/>
        <TestInput name="foo" value="foo" required/>
      </Formsy.Form>
    );

    expect(isRequireds[0]()).toBe(false);
    expect(isRequireds[1]()).toBe(true);

  });

  it('should return true or false when calling showRequired() depending on input being empty and required is passed, or not', function () {

    var showRequireds = [];
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        showRequireds.push(this.showRequired);
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="A" value="foo"/>
        <TestInput name="B" value="" required/>
        <TestInput name="C" value=""/>
      </Formsy.Form>
    );

    expect(showRequireds[0]()).toBe(false);
    expect(showRequireds[1]()).toBe(true);
    expect(showRequireds[2]()).toBe(false);

  });

  it('should return true or false when calling showError() depending on value is invalid or a server error has arrived, or not', function (done) {

    var showError = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        showError = this.showError;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="foo" value="foo" validations="isEmail" validationError="This is not an email"/>
      </Formsy.Form>
    );

    expect(showError()).toBe(true);

    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo@foo.com'}});
    expect(showError()).toBe(false);

    jasmine.Ajax.install();
    TestUtils.Simulate.submit(form.getDOMNode());
    jasmine.Ajax.requests.mostRecent().respondWith({
      status: 500,
      responseType: 'application/json',
      responseText: '{"foo": "Email already exists"}'
    });
    setTimeout(function () {
      expect(showError()).toBe(true);
      jasmine.Ajax.uninstall();
      done();
    }, 0);
  });

  it('should return true or false when calling isPristine() depending on input has been "touched" or not', function () {

    var isPristine = null;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      componentDidMount: function () {
        isPristine = this.isPristine;
      },
      updateValue: function (event) {
        this.setValue(event.target.value);
      },
      render: function () {
        return <input value={this.getValue()} onChange={this.updateValue}/>
      }
    });
    var form = TestUtils.renderIntoDocument(
      <Formsy.Form url="/users">
        <TestInput name="A" value="foo"/>
      </Formsy.Form>
    );

    expect(isPristine()).toBe(true);
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    TestUtils.Simulate.change(input, {target: {value: 'foo'}});
    expect(isPristine()).toBe(false);

  });

it('should allow an undefined value to be updated to a value', function (done) {
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      render: function () {
        return <input value={this.getValue()}/>
      }
    });
    var TestForm = React.createClass({
      getInitialState: function () {
        return {value: undefined};
      },
      changeValue: function () {
        this.setState({
          value: 'foo'
        });
      },
      render: function () {
        return (
          <Formsy.Form url="/users">
            <TestInput name="A" value={this.state.value}/>
          </Formsy.Form>
        );
      }
    });
    var form = TestUtils.renderIntoDocument(
      <TestForm/>
    );

    form.changeValue();
    var input = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
    setTimeout(function () {
      expect(input.getDOMNode().value).toBe('foo');
      done();
    }, 0);
  });

it('should be able to dynamically change validations', function (done) {

    var isInvalid = false;
    var TestInput = React.createClass({
      mixins: [Formsy.Mixin],
      render: function () {
        return <input value={this.getValue()}/>
      }
    });
    var TestForm = React.createClass({
      getInitialState: function () {
        return {value: 'foo@bar.com', validations: 'isEmail'};
      },
      changeValidations: function () {
        this.setState({
          validations: 'equals:foo'
        });
      },
      setInvalid: function () {
        console.log('Running it!');
        isInvalid = true;
      },
      render: function () {
        return (
          <Formsy.Form url="/users" onInvalid={this.setInvalid}>
            <TestInput name="A" validations={this.state.validations} value={this.state.value}/>
          </Formsy.Form>
        );
      }
    });
    var form = TestUtils.renderIntoDocument(
      <TestForm/>
    );

    form.changeValidations();
    setTimeout(function () {
      expect(isInvalid).toBe(true);
      done();
    }, 0);
  });

});
<|endoftext|>


<commit_before>/**********************************************************
 * Copyright (c) SESHENGHUO.COM All rights reserved       *
 **********************************************************/

/**
 * 字符串工具模块
 * @charset utf-8
 * @author lijun
 * @git: https://github.com/zwlijun/se.builder
 * @date 2014.4
 */
;define(function StringUtil(require, exports, module) {

    module.exports = {
        /**
         * 替换所有匹配的字符/字符串
         * @param String instr 输入的字符串
         * @param String regexp 需要替换的字符/字符串
         * @param String replacement 替换的字符/字符串
         * @return String 替换后的字符串
         */
        replaceAll : function(instr, regexp, replacement){
            var pattern = new RegExp(regexp, "gm");
            var tmp = instr.replace(pattern, replacement);
            pattern = null;
            return tmp;
        },
        /**
         * 替换第一次匹配的字符/字符串
         * @param String instr 输入的字符串
         * @param String regexp 需要替换的字符/字符串
         * @param String replacement 替换的字符/字符串
         * @return String 替换后的字符串
         */
        replaceFirst : function(instr, regexp, replacement){
            var group = new RegExp("("+ regexp + ")", "gm").exec(instr);
            var tmp = instr;
            if (null !== group){
                tmp = instr.substring(0, group.index)
                    .concat(replacement)
                    .concat(instr.substring(group.index+group[1].length));
            }
            group = null;
            return tmp;
        },
        /**
         * 匹配字符串是否以prefix开头
         * @param String instr 输入的字符串
         * @param String prefix 前缀
         * @param Number offset 起始的偏移位置
         * @return Boolean true/false
         */
        startsWith : function(instr, prefix, offset){
            offset = typeof(offset) == "number" ? offset : 0;
            if (instr.length >= (prefix.length + offset)){
                return (instr.substr(offset, prefix.length) == prefix);
            }else{
                return false;
            }
        },
        /**
         * 匹配字符串是否以suffix结尾
         * @param String instr 输入的字符串
         * @param String suffix
         * @return Boolean true/false
         */
        endsWith : function(instr, suffix){
            if (instr.length >= suffix.length){
                return (instr.substr((instr.length - suffix.length), suffix.length) == suffix);
            }else{
                return false;
            }
        },
         /**
         * 去两端空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trim : function(instr){
            var pattern = /^([\s ]+)|([\s ]+)$/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 去左空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trimLeft : function(instr){
            var pattern = /^[\s ]+/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 去右空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trimRight : function(instr){
            var pattern = /[\s ]+$/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 字符串长度，将中文看成两个字符计算
         * @param String instr 输入的字符串
         * @return Number 字符串长度
         */
        length : function(instr){
            return instr.replace(/[^\u0000-\u00FF]/gmi, "**").length;
        },
        /**
         * 前导填充
         * @param String instr 输入的字符串
         * @param String chr 填充的字符
         * @param Number bit 位数
         * @return String 填充后的字符串
         */
        fillBefore : function(instr, chr, bit){
            var len = instr.length;
            var shift = bit - len + 1;
            var str = instr;
            if(shift > 0){
                var a = new Array(shift);
                str = a.join(chr) + str;
                a = null;
            }
            return str;
        },
        /**
         * 向后填充
         * @param String instr 输入的字符串
         * @param String chr 填充的字符
         * @param Number bit 位数
         * @return String 填充后的字符串
         */
        fillAfter : function(instr, chr, bit){
            var len = instr.length;
            var shift = bit - len + 1;
            var str = instr;
            if(shift > 0){
                var a = new Array(shift);
                str = str + a.join(chr);
                a = null;
            }
            return str;
        },
        /**
         * 转换成货币格式(支持超大金额)
         * @param String amount 输入的字符串
         * @param int digit 小数位数
         * @return String 转换后的货币
         */
        toCurrency: function(amount, digit){
            var str = amount + "";
            var group = str.split(".");
            var prefix = group[0];
            var suffix = group[1] || "";
            var len = suffix.length;

            digit = Number(digit);
            digit = isNaN(digit) ? 2 : Math.min(digit, 6);

            if(digit > 0){
                if(len < digit){
                    suffix = suffix + new Array(digit - len + 1).join("0")
                }else if(len == digit){
                    suffix = suffix;
                }else{
                    var tmp = suffix.substring(0, digit);
                    var last = Number(tmp.substring(digit - 1));
                    var cut = Number(suffix.substring(digit, digit + 1));

                    if(cut >= 5){
                        tmp = Number(tmp) + 1;
                    }
                    suffix = tmp + "";
                }
            }

            //如果小数位为0或者suffix计算后的长度 > 设置的小数位，测对主体进行进位操作
            if((digit === 0 && suffix) || (suffix.length - digit === 1)){
                var tmp = Number(suffix.charAt(0));
                var arr = prefix.split("");
                var n = 0;
                var o = 1;
                var buf = [];

                //小数溢出
                if(suffix.length - digit === 1){
                    tmp = 5;
                    suffix = suffix.substring(1);
                }

                if(tmp >= 5){
                    for(var i = arr.length - 1; i >= 0; i--){
                        n = Number(arr[i]);

                        n += o;

                        if(n == 10){
                            buf.unshift(0);
                            o = 1;
                        }else{
                            buf.unshift(n);
                            o = 0;
                            break;
                        }
                    }

                    if(o ===1){
                        buf.unshift(1);
                    }

                    prefix = buf.join("");
                }
            }

            prefix = prefix.split("")
                           .reverse()
                           .join("")
                           .replace(/([\d]{3})/g, "$1,")
                           .split("")
                           .reverse()
                           .join("")
                           .replace(/^([\+\-]?)(?=,),([\d,]+)$/, "$1$2");

            return digit > 0 ? prefix + "." + suffix : prefix;
        },
        /**
         * 将字符串转换成十六进制
         * @param String str 原串
         * @return String hex
         */
        string2hex : function(str){
            var len = str.length;
            var hex = '';
            var code = 0;

            for(var i = 0; i < len; i++){
                code = str.charCodeAt(i);

                if(code < 127){
                    hex += "00" + code.toString(16);
                }else{
                    hex += code.toString(16);
                }
            }

            return hex;
        },
        /**
         * 将十六进制转换成字符串
         * @param String hex 十六进制串
         * @return String str
         */
        hex2string : function(hex){
            var len = hex.length;
            var str = "";
            var code = 0;

            for(var i = 0; i < len; i += 4){
                code = parseInt(hex.substr(i, 4), 16);
                str += String.fromCharCode(code);
            }

            return str;
        }
    };
});<commit_msg>优化toCurrency方法<commit_after>/**********************************************************
 * Copyright (c) SESHENGHUO.COM All rights reserved       *
 **********************************************************/

/**
 * 字符串工具模块
 * @charset utf-8
 * @author lijun
 * @git: https://github.com/zwlijun/se.builder
 * @date 2014.4
 */
;define(function StringUtil(require, exports, module) {

    module.exports = {
        /**
         * 替换所有匹配的字符/字符串
         * @param String instr 输入的字符串
         * @param String regexp 需要替换的字符/字符串
         * @param String replacement 替换的字符/字符串
         * @return String 替换后的字符串
         */
        replaceAll : function(instr, regexp, replacement){
            var pattern = new RegExp(regexp, "gm");
            var tmp = instr.replace(pattern, replacement);
            pattern = null;
            return tmp;
        },
        /**
         * 替换第一次匹配的字符/字符串
         * @param String instr 输入的字符串
         * @param String regexp 需要替换的字符/字符串
         * @param String replacement 替换的字符/字符串
         * @return String 替换后的字符串
         */
        replaceFirst : function(instr, regexp, replacement){
            var group = new RegExp("("+ regexp + ")", "gm").exec(instr);
            var tmp = instr;
            if (null !== group){
                tmp = instr.substring(0, group.index)
                    .concat(replacement)
                    .concat(instr.substring(group.index+group[1].length));
            }
            group = null;
            return tmp;
        },
        /**
         * 匹配字符串是否以prefix开头
         * @param String instr 输入的字符串
         * @param String prefix 前缀
         * @param Number offset 起始的偏移位置
         * @return Boolean true/false
         */
        startsWith : function(instr, prefix, offset){
            offset = typeof(offset) == "number" ? offset : 0;
            if (instr.length >= (prefix.length + offset)){
                return (instr.substr(offset, prefix.length) == prefix);
            }else{
                return false;
            }
        },
        /**
         * 匹配字符串是否以suffix结尾
         * @param String instr 输入的字符串
         * @param String suffix
         * @return Boolean true/false
         */
        endsWith : function(instr, suffix){
            if (instr.length >= suffix.length){
                return (instr.substr((instr.length - suffix.length), suffix.length) == suffix);
            }else{
                return false;
            }
        },
         /**
         * 去两端空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trim : function(instr){
            var pattern = /^([\s ]+)|([\s ]+)$/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 去左空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trimLeft : function(instr){
            var pattern = /^[\s ]+/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 去右空字符
         * @param String instr 输入的字符串
         * @return String 去空后的字符串
         */
        trimRight : function(instr){
            var pattern = /[\s ]+$/gmi;
            var tmp = instr.replace(pattern, "");
            pattern = null;
            return tmp;
        },
        /**
         * 字符串长度，将中文看成两个字符计算
         * @param String instr 输入的字符串
         * @return Number 字符串长度
         */
        length : function(instr){
            return instr.replace(/[^\u0000-\u00FF]/gmi, "**").length;
        },
        /**
         * 前导填充
         * @param String instr 输入的字符串
         * @param String chr 填充的字符
         * @param Number bit 位数
         * @return String 填充后的字符串
         */
        fillBefore : function(instr, chr, bit){
            var len = instr.length;
            var shift = bit - len + 1;
            var str = instr;
            if(shift > 0){
                var a = new Array(shift);
                str = a.join(chr) + str;
                a = null;
            }
            return str;
        },
        /**
         * 向后填充
         * @param String instr 输入的字符串
         * @param String chr 填充的字符
         * @param Number bit 位数
         * @return String 填充后的字符串
         */
        fillAfter : function(instr, chr, bit){
            var len = instr.length;
            var shift = bit - len + 1;
            var str = instr;
            if(shift > 0){
                var a = new Array(shift);
                str = str + a.join(chr);
                a = null;
            }
            return str;
        },
        /**
         * 千分位格式化
         * @param String currency 货币金额
         * @param Boolean trimTailZero 是否过滤小数位后的未尾0
         * @return String 转换后的货币
         */
        formatMaskCurrency: function(currency, trimTailZero){
            if(null == currency){
                return "??";
            }
            var dotIndex = -1;
            var hasDot = -1 != (dotIndex = currency.indexOf("."));
            var prefix = hasDot ? currency.substring(0, dotIndex) : currency;
            var suffix = hasDot ? currency.substring(dotIndex) : "";

            if(suffix.length > 0 && true == trimTailZero){
                suffix = suffix.replace(/0+$/g, "");
                if("." == suffix){
                    suffix = "";
                }
            }

            var formatCurrent = prefix.replace(/([a-zA-Z\d\?\*])(?=(?:[a-zA-Z\d\?\*]{3})+$)/g, "$1,") + suffix;

            return formatCurrent;
        },
        /**
         * 转换成货币格式(支持超大金额)
         * @param String amount 输入的字符串
         * @param int digit 小数位数
         * @param Boolean trimTailZero 是否过滤小数位后的未尾0
         * @return String 转换后的货币
         */
        toCurrency: function(amount, digit, trimTailZero){
            if(!isNaN(Number(amount + ""))){
                var str = amount + "";
                var group = str.split(".");
                var prefix = group[0];
                var suffix = group[1] || "";
                var len = suffix.length;

                digit = Number(digit);
                digit = isNaN(digit) ? 2 : Math.min(digit, 6);

                if(digit > 0){
                    if(len < digit){
                        suffix = suffix + new Array(digit - len + 1).join("0")
                    }else if(len == digit){
                        suffix = suffix;
                    }else{
                        var tmp = suffix.substring(0, digit);
                        var last = Number(tmp.substring(digit - 1));
                        var cut = Number(suffix.substring(digit, digit + 1));

                        if(cut >= 5){
                            tmp = Number(tmp) + 1;
                        }
                        suffix = tmp + "";
                    }
                }

                //如果小数位为0或者suffix计算后的长度 > 设置的小数位，测对主体进行进位操作
                if((digit === 0 && suffix) || (suffix.length - digit === 1)){
                    var tmp = Number(suffix.charAt(0));
                    var arr = prefix.split("");
                    var n = 0;
                    var o = 1;
                    var buf = [];

                    //小数溢出
                    if(suffix.length - digit === 1){
                        tmp = 5;
                        suffix = suffix.substring(1);
                    }

                    if(tmp >= 5){
                        for(var i = arr.length - 1; i >= 0; i--){
                            n = Number(arr[i]);

                            n += o;

                            if(n == 10){
                                buf.unshift(0);
                                o = 1;
                            }else{
                                buf.unshift(n);
                                o = 0;
                                break;
                            }
                        }

                        if(o ===1){
                            buf.unshift(1);
                        }

                        prefix = buf.join("");
                    }
                }

                amount = digit > 0 ? prefix + "." + suffix : prefix;
            }

            return this.formatMaskCurrency(amount, true === trimTailZero);
        },
        /**
         * 将字符串转换成十六进制
         * @param String str 原串
         * @return String hex
         */
        string2hex : function(str){
            var len = str.length;
            var hex = '';
            var code = 0;

            for(var i = 0; i < len; i++){
                code = str.charCodeAt(i);

                if(code < 127){
                    hex += "00" + code.toString(16);
                }else{
                    hex += code.toString(16);
                }
            }

            return hex;
        },
        /**
         * 将十六进制转换成字符串
         * @param String hex 十六进制串
         * @return String str
         */
        hex2string : function(hex){
            var len = hex.length;
            var str = "";
            var code = 0;

            for(var i = 0; i < len; i += 4){
                code = parseInt(hex.substr(i, 4), 16);
                str += String.fromCharCode(code);
            }

            return str;
        }
    };
});<|endoftext|>


<commit_before>/**
 * UB-RIA-UI 1.0
 * Copyright 2014 Baidu Inc. All rights reserved.
 *
 * @file 带load型选择器的富选择控件组合
 * @exports FilterRichSelectorGroup
 * @author lixiang(lixiang05@baidu.com)
 */
define(
    function (require) {
        var u = require('underscore');
        var Panel = require('esui/Panel');

        /**
         * 带load型选择器的富选择控件组合由：
         * --- 一个Load型富选择器（必选）
         * --- 一个Add型富选择器（必选）
         * --- 一个Delete型富选择器（可选）
         * 组成
         *
         * 支持根据Load型选择器的选择动态加载备选资源的交互
         *
         * 三个选择控件的类型以及配置由使用者通过模板自行定义，详情参见demo
         *
         * 选择控件必须配置data-ui-role，'filter'代表筛选器 'source'代表源选择器，'target'代表目标选择器
         *
         * @class FilterRichSelectorGroup
         * @extends esui.Panel
         */
        var exports = {};

        /**
         * @override
         */
        exports.type = 'FilterRichSelectorGroup';

        exports.getCategory = function () {
            return 'input';
        };

        exports.initOptions = function (options) {
            var properties = {
                multi: true,
                sourceData: [],
                sourceSelectedData: []
            };

            u.extend(properties, options);
            parseBoolean(properties);

            this.$super([properties]);
        };

        function parseBoolean(properties) {
            u.each(properties, function (property, key) {
                if (property === 'false') {
                    properties[key] = false;
                }
            });
        }

        /**
         * @override
         */
        exports.initStructure = function () {
            this.helper.initChildren();

            // 获取children
            var selectors = this.children;
            u.each(
                selectors,
                function (selector) {
                    var role = selector.main.getAttribute('data-ui-role');
                    if (role) {
                        this[role] = selector;
                    }
                },
                this
            );

            // 绑事件
            this.filter.on(
                'load',
                function (e) {
                    var event = this.fire('load', {item: e.item});
                    if (event.isDefaultPrevented()) {
                        return;
                    }
                    var data = event.data;
                    // 从data中筛选出已选择的，勾选上
                    var selectedItems = u.filter(
                        data,
                        function (item) {
                            return u.findWhere(this.getRawValue(), {id: item.id}) != null;
                        },
                        this
                    );

                    this.source.setProperties({datasource: data, selectedData: selectedItems});
                },
                this
            );

            this.source.on(
                'add',
                function (e) {
                    var items = e.target.getSelectedItems();
                    if (items.length) {
                        var event = this.fire('add', {items: items});
                        // 外部有自己的添加处理逻辑
                        if (event.isDefaultPrevented()) {
                            return;
                        }
                        // 默认的处理：
                        // 条件：默认source是TableRichSelector
                        // 情景1：有target，则分组多选，选择的结果要叠加
                        // 情景2：没有target，则分组单选，结果不叠加
                        var newSelecteItems;
                        // 情景1
                        if (this.target) {
                            // 获取原始的已选值
                            newSelecteItems = u.deepClone(this.getRawValue()) || [];
                            // 单选
                            if (e.item) {
                                // 添加
                                if (e.status) {
                                    var selectedItem = u.omit(e.item, e.item.isSelected);
                                    // 追加
                                    newSelecteItems.push(selectedItem);
                                }
                                // 反选删除
                                else {
                                    // 过滤
                                    newSelecteItems = u.filter(
                                        newSelecteItems,
                                        function (item) {
                                            item.id !== e.item.id;
                                        }
                                    );
                                }
                            }
                            // 批量添加
                            else {
                                // 选择源当前选择项
                                var selectedItems = e.target.getSelectedItems();
                                newSelecteItems = u.union(newSelecteItems, selectedItems);
                            }
                            this.target.setProperties({datasource: newSelecteItems});
                        }
                        // 情景2
                        else {
                            newSelecteItems = this.source.getSelectedItems();
                        }
                        this.rawValue = newSelecteItems;
                        this.fire('change');
                    }
                },
                this
            );

            this.target && this.target.on(
                'delete',
                function (arg) {
                    var items = arg.items;
                    var event = this.fire('delete', {items: items});
                    if (event.isDefaultPrevented()) {
                        return;
                    }
                    // 默认将source中的指定数据取消选择
                    this.source && this.source.selectItems(items, false);
                    this.fire('change');
                },
                this
            );
        };

        /**
         * 重新渲染视图
         * 仅当生命周期处于RENDER时，该方法才重新渲染
         *
         * @param {Array=} 变更过的属性的集合
         * @override
         */
        exports.repaint = require('esui/painters').createRepaint(
            Panel.prototype.repaint,
            {
                name: 'rawValue',
                paint: function (control, rawValue) {
                    control.target && control.target.setProperties({datasource: rawValue});
                }
            },
            {
                name: 'filterData',
                paint: function (control, filterData) {
                    control.filter && control.filter.setProperties({datasource: filterData});
                }
            },
            {
                name: ['sourceData', 'sourceSelectedData'],
                paint: function (control, sourceData, sourceSelectedData) {
                    var properties = {datasource: sourceData, selectedData: sourceSelectedData};
                    control.source && control.source.setProperties(properties);
                }
            }
        );

        /**
         * 将value从原始格式转换成string
         *
         * @param {*} rawValue 原始值
         * @return {string}
         */
        exports.stringifyValue = function (rawValue) {
            var selectedIds = [];
            if (!u.isArray(rawValue)) {
                selectedIds = [rawValue];
            }
            else {
                u.each(rawValue, function (item) {
                    selectedIds.push(item.id);
                });
            }
            return selectedIds.join(',');
        };

        exports.getRawValue = function () {
            if (this.target) {
                return this.target.getRawValue();
            }
            return this.rawValue;
        };

        var FilterRichSelectorGroup = require('eoo').create(Panel, exports);
        require('esui').register(FilterRichSelectorGroup);

        return FilterRichSelectorGroup;
    }
);
<commit_msg>去掉不必要的boolean处理<commit_after>/**
 * UB-RIA-UI 1.0
 * Copyright 2014 Baidu Inc. All rights reserved.
 *
 * @file 带load型选择器的富选择控件组合
 * @exports FilterRichSelectorGroup
 * @author lixiang(lixiang05@baidu.com)
 */
define(
    function (require) {
        var u = require('underscore');
        var Panel = require('esui/Panel');

        /**
         * 带load型选择器的富选择控件组合由：
         * --- 一个Load型富选择器（必选）
         * --- 一个Add型富选择器（必选）
         * --- 一个Delete型富选择器（可选）
         * 组成
         *
         * 支持根据Load型选择器的选择动态加载备选资源的交互
         *
         * 三个选择控件的类型以及配置由使用者通过模板自行定义，详情参见demo
         *
         * 选择控件必须配置data-ui-role，'filter'代表筛选器 'source'代表源选择器，'target'代表目标选择器
         *
         * @class FilterRichSelectorGroup
         * @extends esui.Panel
         */
        var exports = {};

        /**
         * @override
         */
        exports.type = 'FilterRichSelectorGroup';

        exports.getCategory = function () {
            return 'input';
        };

        exports.initOptions = function (options) {
            var properties = {
                multi: true,
                sourceData: [],
                sourceSelectedData: []
            };

            u.extend(properties, options);
            this.$super([properties]);
        };

        /**
         * @override
         */
        exports.initStructure = function () {
            this.helper.initChildren();

            // 获取children
            var selectors = this.children;
            u.each(
                selectors,
                function (selector) {
                    var role = selector.main.getAttribute('data-ui-role');
                    if (role) {
                        this[role] = selector;
                    }
                },
                this
            );

            // 绑事件
            this.filter.on(
                'load',
                function (e) {
                    var event = this.fire('load', {item: e.item});
                    if (event.isDefaultPrevented()) {
                        return;
                    }
                    var data = event.data;
                    // 从data中筛选出已选择的，勾选上
                    var selectedItems = u.filter(
                        data,
                        function (item) {
                            return u.findWhere(this.getRawValue(), {id: item.id}) != null;
                        },
                        this
                    );

                    this.source.setProperties({datasource: data, selectedData: selectedItems});
                },
                this
            );

            this.source.on(
                'add',
                function (e) {
                    var items = e.target.getSelectedItems();
                    if (items.length) {
                        var event = this.fire('add', {items: items});
                        // 外部有自己的添加处理逻辑
                        if (event.isDefaultPrevented()) {
                            return;
                        }
                        // 默认的处理：
                        // 条件：默认source是TableRichSelector
                        // 情景1：有target，则分组多选，选择的结果要叠加
                        // 情景2：没有target，则分组单选，结果不叠加
                        var newSelecteItems;
                        // 情景1
                        if (this.target) {
                            // 获取原始的已选值
                            newSelecteItems = u.deepClone(this.getRawValue()) || [];
                            // 单选
                            if (e.item) {
                                // 添加
                                if (e.status) {
                                    var selectedItem = u.omit(e.item, e.item.isSelected);
                                    // 追加
                                    newSelecteItems.push(selectedItem);
                                }
                                // 反选删除
                                else {
                                    // 过滤
                                    newSelecteItems = u.filter(
                                        newSelecteItems,
                                        function (item) {
                                            item.id !== e.item.id;
                                        }
                                    );
                                }
                            }
                            // 批量添加
                            else {
                                // 选择源当前选择项
                                var selectedItems = e.target.getSelectedItems();
                                newSelecteItems = u.union(newSelecteItems, selectedItems);
                            }
                            this.target.setProperties({datasource: newSelecteItems});
                        }
                        // 情景2
                        else {
                            newSelecteItems = this.source.getSelectedItems();
                        }
                        this.rawValue = newSelecteItems;
                        this.fire('change');
                    }
                },
                this
            );

            this.target && this.target.on(
                'delete',
                function (arg) {
                    var items = arg.items;
                    var event = this.fire('delete', {items: items});
                    if (event.isDefaultPrevented()) {
                        return;
                    }
                    // 默认将source中的指定数据取消选择
                    this.source && this.source.selectItems(items, false);
                    this.fire('change');
                },
                this
            );
        };

        /**
         * 重新渲染视图
         * 仅当生命周期处于RENDER时，该方法才重新渲染
         *
         * @param {Array=} 变更过的属性的集合
         * @override
         */
        exports.repaint = require('esui/painters').createRepaint(
            Panel.prototype.repaint,
            {
                name: 'rawValue',
                paint: function (control, rawValue) {
                    control.target && control.target.setProperties({datasource: rawValue});
                }
            },
            {
                name: 'filterData',
                paint: function (control, filterData) {
                    control.filter && control.filter.setProperties({datasource: filterData});
                }
            },
            {
                name: ['sourceData', 'sourceSelectedData'],
                paint: function (control, sourceData, sourceSelectedData) {
                    var properties = {datasource: sourceData, selectedData: sourceSelectedData};
                    control.source && control.source.setProperties(properties);
                }
            }
        );

        /**
         * 将value从原始格式转换成string
         *
         * @param {*} rawValue 原始值
         * @return {string}
         */
        exports.stringifyValue = function (rawValue) {
            var selectedIds = [];
            if (!u.isArray(rawValue)) {
                selectedIds = [rawValue];
            }
            else {
                u.each(rawValue, function (item) {
                    selectedIds.push(item.id);
                });
            }
            return selectedIds.join(',');
        };

        exports.getRawValue = function () {
            if (this.target) {
                return this.target.getRawValue();
            }
            return this.rawValue;
        };

        var FilterRichSelectorGroup = require('eoo').create(Panel, exports);
        require('esui').register(FilterRichSelectorGroup);

        return FilterRichSelectorGroup;
    }
);
<|endoftext|>


<commit_before>'use strict';

window.addEventListener('load', function() {
    var editor = ContentTools.EditorApp.get();

    var defineStyles = function() {
        ContentTools.StylePalette.add([
            new ContentTools.Style('Chapo', 'chapo', ['p']),
            new ContentTools.Style('Exergue', 'exergue', ['p', 'img']),
            new ContentTools.Style('Citation', 'quote', ['p']),
            new ContentTools.Style('Question', 'question', ['p']),
            new ContentTools.Style('Appui', 'fold', ['p'])
        ]);
    };

    var defineTools = function() {
        var createToolWithPopup = function(attrName, className) {
            var Tool = _.clone(ContentTools.ToolShelf.fetch('bold'));

            Tool.getStuff = function(element, selection) {
                var sFrom = selection.get()[0],
                    sTo = selection.get()[1],
                    selectedContent = element.content.slice(sFrom, sTo);

                for (var c in selectedContent.characters) {
                    c = selectedContent.characters[c];

                    if (!c.hasTags(Tool.tagName)) {
                        continue;
                    }

                    for (var tag in c.tags()) {
                        tag = c.tags()[tag];
                        if (tag.name() === Tool.tagName) {
                            return tag.attr(attrName);
                        }
                    }
                }

                return '';
            };

            Tool.apply = function(element, selection, callback) {
                var app = ContentTools.EditorApp.get(),
                    selectTag = new HTMLString.Tag('span', { class : 'ct--pseudo-select' }),
                    sFrom = selection.get()[0], sTo = selection.get()[1],
                    dialog,
                    modal = new ContentTools.ModalUI({transparent:true,allowScrolling:true});

                element.storeState();

                element.content = element.content.format(sFrom, sTo, selectTag);
                element.updateInnerHTML();

                modal.bind('click', function() {
                    this.unmount();
                    dialog.hide();

                    element.content = element.content.unformat(sFrom, sTo, selectTag);
                    element.updateInnerHTML();

                    element.restoreState();

                    callback(false);
                });

                var domElement = element.domElement(),
                    measureSpan = domElement.getElementsByClassName('ct--pseudo-select'),
                    rect = measureSpan[0].getBoundingClientRect();

                dialog = new ContentTools.LinkDialog(this.getStuff(element, selection));
                (function() {
                    var mount = dialog.mount;
                    dialog.mount = function() {
                        var ret = mount.bind(this)();
                        this._domInput.setAttribute('placeholder', Tool.label);
                        return ret;
                    };
                })();
                dialog.position([
                    rect.left + (rect.width / 2) + window.scrollX,
                    rect.top + (rect.height / 2) + window.scrollY
                ]);
                dialog.bind('save', function(stuff) {
                    element.content = element.content.unformat(sFrom, sTo, Tool.tagName);

                    if (stuff != null) {
                        var htmlStringAttrs = { class : className };
                        htmlStringAttrs[attrName] = stuff;
                        element.content = element.content.format(
                            sFrom,
                            sTo,
                            new HTMLString.Tag(Tool.tagName, htmlStringAttrs)
                        );
                    }

                    element.updateInnerHTML();
                    element.taint();

                    modal.unmount();
                    dialog.hide();

                    element.content = element.content.unformat(sFrom, sTo, selectTag);
                    element.updateInnerHTML();

                    element.restoreState();

                    callback(true);
                });

                app.attach(modal);
                app.attach(dialog);
                modal.show();
                dialog.show();
            };

            return Tool;
        };

        // Superscript
        (function() {
            var Tool = _.clone(ContentTools.ToolShelf.fetch('bold'));
            Tool.label = 'Superscript';
            Tool.icon = 'superscript';
            Tool.tagName = 'sup';
            ContentTools.ToolShelf.stow(Tool, 'superscript');
        })();

        // Definition
        (function() {
            var Tool = createToolWithPopup('rel', 'definition');

            Tool.label = 'Définition';
            Tool.icon = 'definition';
            Tool.tagName = 'span';

            ContentTools.ToolShelf.stow(Tool, 'definition');
        })();

        // Video
        (function() {
            var Tool = createToolWithPopup('href', 'videolink');

            Tool.label = 'Lien vidéo';
            Tool.icon = 'youtube2';
            Tool.tagName = 'a';

            ContentTools.ToolShelf.stow(Tool, 'videolink');
        })();
    };

    var onStopEdit = function() {
        $('.chapter__content > *').each(function() {
            if ($(this).hasClass('menu')) { return; }
            $(this).html($(this).html().replace('&nbsp;', ' '));
        });

        window.resetComponents();
    };

    var startEditor = function() {
        editor.init('.chapter__content', 'data-name');

        $('.ct-ignition__button--cancel').click(function() {
            onStopEdit();
        });

        $('.ct-ignition__button--edit')[0].addEventListener('click', function() {
            $('.chapter__content > *').each(function() {
                if ($(this).hasClass('menu')) { return; }
                $(this).html($(this).html().replace(' ', '&nbsp;'));
            });
        });

        $('.ct-widget').append(
            $('<div>', {
                class : 'ct-ignition__button ct-ignition__button--add-chapter'
            }).click(function() {
                editor.busy(true);
                $.post('/add', function(data, status) {
                    editor.busy(false);
                    if (status === 'success') {
                        new ContentTools.FlashUI('ok');
                        $('.content').append(data);
                        $('ul').append(
                            $('<li>').append(
                                $('<a>', {
                                    href : '#' + $('section:last-of-type').attr('id')
                                }).text('Chapitre ' + String($('section').length))
                            )
                        );
                        editor.destroy();
                        startEditor();
                    } else {
                        new ContentTools.FlashUI('no');
                    }
                });
            })
        );

        onStopEdit();
    };

    ContentTools.DEFAULT_TOOLS = [
        ['bold', 'italic', 'link'],
        ['heading', 'subheading', 'paragraph'],
        ['superscript', 'definition', 'videolink'],
        ['line-break', 'image'],
        ['undo', 'redo', 'remove']
    ];

    editor.bind('save', function(regions) {
        editor.busy(true);

        var data = { };
        for (var k in regions) {
            if (regions.hasOwnProperty(k) && k.indexOf('chapitre-') === 0) {
                data[k.replace('chapitre-', '')] = regions[k];
            }
        }

        $.post('/save', data, function(_, status) {
            onStopEdit();

            editor.busy(false);
            if (status === 'success') {
                new ContentTools.FlashUI('ok');
            } else {
                new ContentTools.FlashUI('no');
            }
        });
    });

    ContentTools.IMAGE_UPLOADER = function(dialog) {
        var image, xhr, xhrComplete, xhrProgress;

        dialog.bind('imageUploader.cancelUpload', function() {
            if (xhr != null) {
                xhr.upload.removeEventListener('progress', xhrProgress);
                xhr.removeEventListener('readystatechange', xhrComplete);
                xhr.abort();
            }
            dialog.state('empty');
        });

        dialog.bind('imageUploader.clear', function() {
            dialog.clear();
            image = null;
        });

        dialog.bind('imageUploader.fileReady', function(file) {
            var formData;

            xhrProgress = function(ev) {
                dialog.progress((ev.loaded / ev.total) * 100);
            };

            xhrComplete = function(ev) {
                var response;

                if (ev.target.readyState !== 4) {
                    return;
                }

                xhr = xhrProgress = xhrComplete = null;

                if (parseInt(ev.target.status) === 200) {
                    response = JSON.parse(ev.target.responseText);

                    image = new Image();
                    image.onload = function() {
                        image = {
                            url : response.url,
                            size : [this.width, this.height]
                        };

                        dialog.populate(image.url, image.size);
                    };
                    image.src = response.url;
                } else {
                    new ContentTools.FlashUI('no');
                }
            };

            dialog.state('uploading');
            dialog.progress(0);

            formData = new FormData();
            formData.append('image', file);

            xhr = new XMLHttpRequest();
            xhr.upload.addEventListener('progress', xhrProgress);
            xhr.addEventListener('readystatechange', xhrComplete);
            xhr.open('POST', '/upload-image', true);
            xhr.send(formData);
        });

        dialog.bind('imageUploader.save', function() {
            if (image != null && image.url != null) {
                dialog.save(image.url, image.size);
            } else {
                new ContentTools.FlashUI('no');
            }
        });
    };

    defineStyles();
    defineTools();
    if ($('.chapter__content').length > 0) {
        startEditor();
    } else {
        $.post('/add', { }, function() {
            window.location.reload();
        });
    }
});
<commit_msg>auto open folds when editing<commit_after>'use strict';

window.addEventListener('load', function() {
    var editor = ContentTools.EditorApp.get();

    var defineStyles = function() {
        ContentTools.StylePalette.add([
            new ContentTools.Style('Chapo', 'chapo', ['p']),
            new ContentTools.Style('Exergue', 'exergue', ['p', 'img']),
            new ContentTools.Style('Citation', 'quote', ['p']),
            new ContentTools.Style('Question', 'question', ['p']),
            new ContentTools.Style('Appui', 'fold', ['p'])
        ]);
    };

    var defineTools = function() {
        var createToolWithPopup = function(attrName, className) {
            var Tool = _.clone(ContentTools.ToolShelf.fetch('bold'));

            Tool.getStuff = function(element, selection) {
                var sFrom = selection.get()[0],
                    sTo = selection.get()[1],
                    selectedContent = element.content.slice(sFrom, sTo);

                for (var c in selectedContent.characters) {
                    c = selectedContent.characters[c];

                    if (!c.hasTags(Tool.tagName)) {
                        continue;
                    }

                    for (var tag in c.tags()) {
                        tag = c.tags()[tag];
                        if (tag.name() === Tool.tagName) {
                            return tag.attr(attrName);
                        }
                    }
                }

                return '';
            };

            Tool.apply = function(element, selection, callback) {
                var app = ContentTools.EditorApp.get(),
                    selectTag = new HTMLString.Tag('span', { class : 'ct--pseudo-select' }),
                    sFrom = selection.get()[0], sTo = selection.get()[1],
                    dialog,
                    modal = new ContentTools.ModalUI({transparent:true,allowScrolling:true});

                element.storeState();

                element.content = element.content.format(sFrom, sTo, selectTag);
                element.updateInnerHTML();

                modal.bind('click', function() {
                    this.unmount();
                    dialog.hide();

                    element.content = element.content.unformat(sFrom, sTo, selectTag);
                    element.updateInnerHTML();

                    element.restoreState();

                    callback(false);
                });

                var domElement = element.domElement(),
                    measureSpan = domElement.getElementsByClassName('ct--pseudo-select'),
                    rect = measureSpan[0].getBoundingClientRect();

                dialog = new ContentTools.LinkDialog(this.getStuff(element, selection));
                (function() {
                    var mount = dialog.mount;
                    dialog.mount = function() {
                        var ret = mount.bind(this)();
                        this._domInput.setAttribute('placeholder', Tool.label);
                        return ret;
                    };
                })();
                dialog.position([
                    rect.left + (rect.width / 2) + window.scrollX,
                    rect.top + (rect.height / 2) + window.scrollY
                ]);
                dialog.bind('save', function(stuff) {
                    element.content = element.content.unformat(sFrom, sTo, Tool.tagName);

                    if (stuff != null) {
                        var htmlStringAttrs = { class : className };
                        htmlStringAttrs[attrName] = stuff;
                        element.content = element.content.format(
                            sFrom,
                            sTo,
                            new HTMLString.Tag(Tool.tagName, htmlStringAttrs)
                        );
                    }

                    element.updateInnerHTML();
                    element.taint();

                    modal.unmount();
                    dialog.hide();

                    element.content = element.content.unformat(sFrom, sTo, selectTag);
                    element.updateInnerHTML();

                    element.restoreState();

                    callback(true);
                });

                app.attach(modal);
                app.attach(dialog);
                modal.show();
                dialog.show();
            };

            return Tool;
        };

        // Superscript
        (function() {
            var Tool = _.clone(ContentTools.ToolShelf.fetch('bold'));
            Tool.label = 'Superscript';
            Tool.icon = 'superscript';
            Tool.tagName = 'sup';
            ContentTools.ToolShelf.stow(Tool, 'superscript');
        })();

        // Definition
        (function() {
            var Tool = createToolWithPopup('rel', 'definition');

            Tool.label = 'Définition';
            Tool.icon = 'definition';
            Tool.tagName = 'span';

            ContentTools.ToolShelf.stow(Tool, 'definition');
        })();

        // Video
        (function() {
            var Tool = createToolWithPopup('href', 'videolink');

            Tool.label = 'Lien vidéo';
            Tool.icon = 'youtube2';
            Tool.tagName = 'a';

            ContentTools.ToolShelf.stow(Tool, 'videolink');
        })();
    };

    var onStopEdit = function() {
        $('.chapter__content > *').each(function() {
            if ($(this).hasClass('menu')) { return; }
            $(this).html($(this).html().replace('&nbsp;', ' '));
        });

        window.resetComponents();
    };

    var startEditor = function() {
        editor.init('.chapter__content', 'data-name');

        $('.ct-ignition__button--cancel').click(function() {
            onStopEdit();
        });

        $('.ct-ignition__button--edit')[0].addEventListener('click', function() {
            $('.fold.folded').removeClass('folded');

            $('.chapter__content > *').each(function() {
                if ($(this).hasClass('menu')) { return; }
                $(this).html($(this).html().replace(' ', '&nbsp;'));
            });
        });

        $('.ct-widget').append(
            $('<div>', {
                class : 'ct-ignition__button ct-ignition__button--add-chapter'
            }).click(function() {
                editor.busy(true);
                $.post('/add', function(data, status) {
                    editor.busy(false);
                    if (status === 'success') {
                        new ContentTools.FlashUI('ok');
                        $('.content').append(data);
                        $('ul').append(
                            $('<li>').append(
                                $('<a>', {
                                    href : '#' + $('section:last-of-type').attr('id')
                                }).text('Chapitre ' + String($('section').length))
                            )
                        );
                        editor.destroy();
                        startEditor();
                    } else {
                        new ContentTools.FlashUI('no');
                    }
                });
            })
        );

        onStopEdit();
    };

    ContentTools.DEFAULT_TOOLS = [
        ['bold', 'italic', 'link'],
        ['heading', 'subheading', 'paragraph'],
        ['superscript', 'definition', 'videolink'],
        ['line-break', 'image'],
        ['undo', 'redo', 'remove']
    ];

    editor.bind('save', function(regions) {
        editor.busy(true);

        var data = { };
        for (var k in regions) {
            if (regions.hasOwnProperty(k) && k.indexOf('chapitre-') === 0) {
                data[k.replace('chapitre-', '')] = regions[k];
            }
        }

        $.post('/save', data, function(_, status) {
            onStopEdit();

            editor.busy(false);
            if (status === 'success') {
                new ContentTools.FlashUI('ok');
            } else {
                new ContentTools.FlashUI('no');
            }
        });
    });

    ContentTools.IMAGE_UPLOADER = function(dialog) {
        var image, xhr, xhrComplete, xhrProgress;

        dialog.bind('imageUploader.cancelUpload', function() {
            if (xhr != null) {
                xhr.upload.removeEventListener('progress', xhrProgress);
                xhr.removeEventListener('readystatechange', xhrComplete);
                xhr.abort();
            }
            dialog.state('empty');
        });

        dialog.bind('imageUploader.clear', function() {
            dialog.clear();
            image = null;
        });

        dialog.bind('imageUploader.fileReady', function(file) {
            var formData;

            xhrProgress = function(ev) {
                dialog.progress((ev.loaded / ev.total) * 100);
            };

            xhrComplete = function(ev) {
                var response;

                if (ev.target.readyState !== 4) {
                    return;
                }

                xhr = xhrProgress = xhrComplete = null;

                if (parseInt(ev.target.status) === 200) {
                    response = JSON.parse(ev.target.responseText);

                    image = new Image();
                    image.onload = function() {
                        image = {
                            url : response.url,
                            size : [this.width, this.height]
                        };

                        dialog.populate(image.url, image.size);
                    };
                    image.src = response.url;
                } else {
                    new ContentTools.FlashUI('no');
                }
            };

            dialog.state('uploading');
            dialog.progress(0);

            formData = new FormData();
            formData.append('image', file);

            xhr = new XMLHttpRequest();
            xhr.upload.addEventListener('progress', xhrProgress);
            xhr.addEventListener('readystatechange', xhrComplete);
            xhr.open('POST', '/upload-image', true);
            xhr.send(formData);
        });

        dialog.bind('imageUploader.save', function() {
            if (image != null && image.url != null) {
                dialog.save(image.url, image.size);
            } else {
                new ContentTools.FlashUI('no');
            }
        });
    };

    defineStyles();
    defineTools();
    if ($('.chapter__content').length > 0) {
        startEditor();
    } else {
        $.post('/add', { }, function() {
            window.location.reload();
        });
    }
});
<|endoftext|>


<commit_before>'use strict';

var Server = require('./Server');
var CollabEngine = require('./CollabEngine');
var forEach = require('lodash/forEach');

/*
  Implements Substance CollabServer API.
*/
function CollabServer(config) {
  CollabServer.super.apply(this, arguments);

  this.scope = 'substance/collab';
  this.documentEngine = config.documentEngine;
  this.collabEngine = new CollabEngine(this.documentEngine);
}

CollabServer.Prototype = function() {
  var _super = CollabServer.super.prototype;

  /*
    Configurable authenticate method
  */
  this.authenticate = function(req, res) {
    if (this.config.authenticate) {
      this.config.authenticate(req, function(err, session) {
        if (err) {
          console.log('Request is not authenticated.');
          res.error(err);
          this.next(req, res);
          return;
        }
        req.setAuthenticated(session);
        this.next(req, res);
      }.bind(this));
    } else {
      _super.authenticate.apply(this, arguments);
    }
  };

  /*
    Configureable enhanceRequest method
  */
  this.enhanceRequest = function(req, res) {
    if (this.config.enhanceRequest) {
      this.config.enhanceRequest(req, function(err) {
        if (err) {
          console.error('enhanceRequest returned an error', err);
          res.error(err);
          this.next(req, res);
          return;
        }
        req.setEnhanced();
        this.next(req, res);
      }.bind(this));
    } else {
      _super.enhanceRequest.apply(this, arguments);
    }
  };

  /*
    Called when a collaborator disconnects
  */
  this.onDisconnect = function(collaboratorId) {
    console.log('CollabServer.onDisconnect ', collaboratorId);
    // All documents collaborator is currently collaborating to
    var documentIds = this.collabEngine.getDocumentIds(collaboratorId);
    documentIds.forEach(function(documentId) {
      this._disconnectDocument(collaboratorId, documentId);
    }.bind(this));
  };

  /*
    Execute CollabServer API method based on msg.type
  */
  this.execute = function(req, res) {
    var msg = req.message;
    var method = this[msg.type];

    if (method) {
      method.call(this, req, res);
    } else {
      console.error('Method', msg.type, 'not implemented for CollabServer');
    }
  };

  /*
    Client initiates a sync
  */
  this.sync = function(req, res) {
    var args = req.message;

    console.log('CollabServer.connect', args.collaboratorId);

    // Takes an optional argument collaboratorInfo
    this.collabEngine.sync(args, function(err, result) {
      // result: changes, version, change
      if (err) {
        res.error(err);
        this.next(req, res);
        return;
      }

      // Get enhance collaborators (e.g. including some app-specific user-info)
      var collaborators = this.collabEngine.getCollaborators(args.documentId, args.collaboratorId);

      // Send the response
      res.send({
        type: 'syncDone',
        documentId: args.documentId,
        version: result.version,
        changes: result.changes,
        collaborators: collaborators
      });

      // We need to broadcast a new change if there is one
      console.log('CollabServer.connect: update is broadcasted to collaborators', Object.keys(collaborators));

      forEach(collaborators, function(collaborator) {
        this.send(collaborator.collaboratorId, {
          type: 'update',
          documentId: args.documentId,
          version: result.version,
          change: result.change,
          // collaboratorId: args.collaboratorId,
          // All except of receiver record
          collaborators: this.collabEngine.getCollaborators(args.documentId, collaborator.collaboratorId)
        });
      }.bind(this));
      this.next(req, res);
    }.bind(this));
  };

  this.disconnect = function(req, res) {
    var args = req.message;
    var collaboratorId = args.collaboratorId;
    var documentId = args.documentId;
    this._disconnectDocument(collaboratorId, documentId);
    // Notify client that disconnect has completed successfully
    res.send({
      type: 'disconnectDone',
      documentId: args.documentId
    });
    this.next(req, res);
  };

  this._disconnectDocument = function(collaboratorId, documentId) {
    var collaboratorIds = this.collabEngine.getCollaboratorIds(documentId, collaboratorId);

    var collaborators = {};
    collaborators[collaboratorId] = null;

    this.broadCast(collaboratorIds, {
      type: 'update',
      documentId: documentId,
      // Removes the entry
      collaborators
    });
    // Exit from each document session
    this.collabEngine.disconnect({
      documentId: documentId,
      collaboratorId: collaboratorId
    });
  };

};

Server.extend(CollabServer);
module.exports = CollabServer;
<commit_msg>Silencio.<commit_after>'use strict';

var Server = require('./Server');
var CollabEngine = require('./CollabEngine');
var forEach = require('lodash/forEach');

/*
  Implements Substance CollabServer API.
*/
function CollabServer(config) {
  CollabServer.super.apply(this, arguments);

  this.scope = 'substance/collab';
  this.documentEngine = config.documentEngine;
  this.collabEngine = new CollabEngine(this.documentEngine);
}

CollabServer.Prototype = function() {
  var _super = CollabServer.super.prototype;

  /*
    Configurable authenticate method
  */
  this.authenticate = function(req, res) {
    if (this.config.authenticate) {
      this.config.authenticate(req, function(err, session) {
        if (err) {
          console.log('Request is not authenticated.');
          res.error(err);
          this.next(req, res);
          return;
        }
        req.setAuthenticated(session);
        this.next(req, res);
      }.bind(this));
    } else {
      _super.authenticate.apply(this, arguments);
    }
  };

  /*
    Configureable enhanceRequest method
  */
  this.enhanceRequest = function(req, res) {
    if (this.config.enhanceRequest) {
      this.config.enhanceRequest(req, function(err) {
        if (err) {
          console.error('enhanceRequest returned an error', err);
          res.error(err);
          this.next(req, res);
          return;
        }
        req.setEnhanced();
        this.next(req, res);
      }.bind(this));
    } else {
      _super.enhanceRequest.apply(this, arguments);
    }
  };

  /*
    Called when a collaborator disconnects
  */
  this.onDisconnect = function(collaboratorId) {
    console.log('CollabServer.onDisconnect ', collaboratorId);
    // All documents collaborator is currently collaborating to
    var documentIds = this.collabEngine.getDocumentIds(collaboratorId);
    documentIds.forEach(function(documentId) {
      this._disconnectDocument(collaboratorId, documentId);
    }.bind(this));
  };

  /*
    Execute CollabServer API method based on msg.type
  */
  this.execute = function(req, res) {
    var msg = req.message;
    var method = this[msg.type];

    if (method) {
      method.call(this, req, res);
    } else {
      console.error('Method', msg.type, 'not implemented for CollabServer');
    }
  };

  /*
    Client initiates a sync
  */
  this.sync = function(req, res) {
    var args = req.message;

    // console.log('CollabServer.connect', args.collaboratorId);

    // Takes an optional argument collaboratorInfo
    this.collabEngine.sync(args, function(err, result) {
      // result: changes, version, change
      if (err) {
        res.error(err);
        this.next(req, res);
        return;
      }

      // Get enhance collaborators (e.g. including some app-specific user-info)
      var collaborators = this.collabEngine.getCollaborators(args.documentId, args.collaboratorId);

      // Send the response
      res.send({
        type: 'syncDone',
        documentId: args.documentId,
        version: result.version,
        changes: result.changes,
        collaborators: collaborators
      });

      // We need to broadcast a new change if there is one
      // console.log('CollabServer.connect: update is broadcasted to collaborators', Object.keys(collaborators));

      forEach(collaborators, function(collaborator) {
        this.send(collaborator.collaboratorId, {
          type: 'update',
          documentId: args.documentId,
          version: result.version,
          change: result.change,
          // collaboratorId: args.collaboratorId,
          // All except of receiver record
          collaborators: this.collabEngine.getCollaborators(args.documentId, collaborator.collaboratorId)
        });
      }.bind(this));
      this.next(req, res);
    }.bind(this));
  };

  this.disconnect = function(req, res) {
    var args = req.message;
    var collaboratorId = args.collaboratorId;
    var documentId = args.documentId;
    this._disconnectDocument(collaboratorId, documentId);
    // Notify client that disconnect has completed successfully
    res.send({
      type: 'disconnectDone',
      documentId: args.documentId
    });
    this.next(req, res);
  };

  this._disconnectDocument = function(collaboratorId, documentId) {
    var collaboratorIds = this.collabEngine.getCollaboratorIds(documentId, collaboratorId);

    var collaborators = {};
    collaborators[collaboratorId] = null;

    this.broadCast(collaboratorIds, {
      type: 'update',
      documentId: documentId,
      // Removes the entry
      collaborators
    });
    // Exit from each document session
    this.collabEngine.disconnect({
      documentId: documentId,
      collaboratorId: collaboratorId
    });
  };

};

Server.extend(CollabServer);
module.exports = CollabServer;
<|endoftext|>


<commit_before>/* WOL fields that should be grouped in match.client object */

module.exports = [
    'vers', /* (str) game client version */
    'vidm', /* (int) client's available video memory */
    'memo', /* (int) client's available pc memory */
    'proc', /* (str) client's processcor family (defunct) */
    'afps', /* (int) average frames per second for match */
    'oosy', /* (bool) whether match was out of sync */
    'gsku', /* (int) game sku */
    'spid', /* (int) sender id? */
    'accn', /* !(str) nick of packet sender */
    'nick', /* !(str) forum account of packet sender */
    'cmpl', /* (int) match completion status */
    'sdfx', /* !(bool) sudden disconnect from game  */
    'quit', /* (bool) whether the player quit */
    'myid', /* !(int) index of uploader in player array */
    'pils', /* !(int) player ping connectivity streak */
    'para', /* !(bool) player aborted recon attempt */
    'unid'
];
<commit_msg>adding new fields<commit_after>/* WOL fields that should be grouped in match.client object */

module.exports = [
    'vers', /* (str) game client version */
    'vidm', /* (int) client's available video memory */
    'memo', /* (int) client's available pc memory */
    'proc', /* (str) client's processcor family (defunct) */
    'afps', /* (int) average frames per second for match */
    'oosy', /* (bool) whether match was out of sync */
    'gsku', /* (int) game sku */
    'spid', /* (int) sender id? */
    'accn', /* !(str) nick of packet sender */
    'nick', /* !(str) forum account of packet sender */
    'cmpl', /* (int) match completion status */
    'sdfx', /* !(bool) sudden disconnect from game  */
    'quit', /* (bool) whether the player quit */
    'myid', /* !(int) index of uploader in player array */
    'pils', /* !(int) player ping connectivity streak */
    'para', /* !(bool) player aborted recon attempt */
    'myip', /* !(str) player's remote address */
    'wine', /* !(bool) player is using wine */
    'utcd', /* !(str) system time settings */
    'unid'
];
<|endoftext|>


<commit_before>// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {fp64ify, fp64LowPart, fp64ifyMatrix4} from './fp64-utils';

import fp64arithmeticShader from './fp64-arithmetic.glsl';
import fp64functionShader from './fp64-functions.glsl';

const fp64shader = `${fp64arithmeticShader}\n${fp64functionShader}`;

export {fp64ify, fp64LowPart, fp64ifyMatrix4};

export default {
  name: 'fp64',
  vs: fp64shader,
  fs: null,
  fp64ify,
  fp64LowPart,
  fp64ifyMatrix4
};

// Arithmetic only
export const fp64arithmetic = {
  name: 'fp64-arithmetic',
  vs: `${fp64arithmeticShader}`,
  fs: null
};

// Fragment shader fp64
export const fp64fs = {
  name: 'fp64-fs',
  vs: null,
  fs: fp64shader
};
<commit_msg>Shader Module fp64: add const uniforms used in shader WAs (#622)<commit_after>// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {fp64ify, fp64LowPart, fp64ifyMatrix4} from './fp64-utils';

import fp64arithmeticShader from './fp64-arithmetic.glsl';
import fp64functionShader from './fp64-functions.glsl';

const fp64shader = `${fp64arithmeticShader}\n${fp64functionShader}`;
const CONST_UNIFORMS = {
  // Used in LUMA_FP64_CODE_ELIMINATION_WORKAROUND
  ONE: 1.0
};
export {fp64ify, fp64LowPart, fp64ifyMatrix4};

function getUniforms() {
  return Object.assign({}, CONST_UNIFORMS);
}

export default {
  name: 'fp64',
  vs: fp64shader,
  fs: null,
  fp64ify,
  fp64LowPart,
  fp64ifyMatrix4,
  getUniforms
};

// Arithmetic only
export const fp64arithmetic = {
  name: 'fp64-arithmetic',
  vs: `${fp64arithmeticShader}`,
  fs: null
};

// Fragment shader fp64
export const fp64fs = {
  name: 'fp64-fs',
  vs: null,
  fs: fp64shader
};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import LocaleSwitcher from './LocaleSwitcher'

export default class Header extends React.Component {

  static propTypes = {
    dispatch: PropTypes.func,
    searchPost: PropTypes.func.isRequired,
    sync: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired,
    search: PropTypes.object.isRequired
  }

  static contextTypes = {
    history: PropTypes.object.isRequired
  }

  constructor (props, context) {
    super(props, context)

    this.state = { userInput: '' }

    this.releaseTimeout = undefined
  }

  componentWillUnmount () {
    if (this.op) {
      clearTimeout(this.releaseTimeout)
    }
  }

  handleChange (event) {
    this.setState({ userInput: event.target.value })
  }

  handleFocus () {
    this.setState({ userInput: '' })
  }

  doSubmit () {
    const pattern = this.state.userInput
    if (!pattern) return

    if (process.env.BROWSER) {
      this.props.searchPost(pattern, 0, 10, true)
      this.releaseTimeout =
        setTimeout(() => this.context.history.replaceState({}, '/search'), 500)
    }

    React.findDOMNode(this.refs.search).blur()
  }

  handleSubmit (event) {
    if (event.which === 13) {
      event.preventDefault()
      this.doSubmit()
    }
  }

  handleSearchSubmit (event) {
    event.preventDefault()
    this.doSubmit()
  }

  render () {
    const { dispatch, auth } = this.props

    const Translate = require('react-translate-component')
    const TranslateProps = React.createFactory(Translate)

    const searchProps = {
      component: 'input',
      type: 'search',
      name: 'q',
      ref: 'search',
      scope: 'search_input',
      attributes: {
        placeholder: 'placeholder',
        title: 'tooltip'
      }
    }

    let AuthLink
    if (!auth.token) {
      AuthLink = (
        <Link to="/login" className="item">
          <Translate content="header.login" />
        </Link>
      )
    } else {
      AuthLink = (
        <Link to="/logout" className="item">
          <Translate content="header.logout" />
        </Link>
      )
    }

    let ChangePasswordLink
    if (auth.token) {
      ChangePasswordLink = (
        <Link to="/password" className="item">
          <Translate content="header.password" />
        </Link>
      )
    }

    let ManageLink
    if (auth.token) {
      ManageLink = (
        <Link to="/manage" className="item">
          <Translate content="header.manage" />
        </Link>
      )
    }

    return (

            <Link to="/home" className="item">
              <Translate content="header.home" />
            </Link>
            <Link to="/w" className="item">
              <Translate content="header.wall" />
            </Link>
            <Link to="/post" className="item">
              <Translate content="header.post" />
            </Link>
            {ChangePasswordLink}
            {ManageLink}

            {AuthLink}
            <LocaleSwitcher dispatch={dispatch} />

              <form
                action=""
                method="post"
                onSubmit={::this.handleSearchSubmit}>

                  <input
                    type="search"
                    ref="search"
                    onChange={::this.handleChange}
                    onFocus={::this.handleFocus}
                    onKeyDown={::this.handleSubmit}
                    value={this.state.userInput}
                  />

                  <input type="submit" className="hide-submit" />

              </form>

            <Link to="/wall/today" className="item left">
              <Translate content="header.home" />
            </Link>
            <Link to="/post" className="item">
              <Translate content="header.post" />
            </Link>
            <LocaleSwitcher dispatch={dispatch} />
            {AuthLink}

    )
  }
}
<commit_msg>add activeClassName<commit_after>import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import LocaleSwitcher from './LocaleSwitcher'

export default class Header extends React.Component {

  static propTypes = {
    dispatch: PropTypes.func,
    searchPost: PropTypes.func.isRequired,
    sync: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired,
    search: PropTypes.object.isRequired
  }

  static contextTypes = {
    history: PropTypes.object.isRequired
  }

  constructor (props, context) {
    super(props, context)

    this.state = { userInput: '' }

    this.releaseTimeout = undefined
  }

  componentWillUnmount () {
    if (this.op) {
      clearTimeout(this.releaseTimeout)
    }
  }

  handleChange (event) {
    this.setState({ userInput: event.target.value })
  }

  handleFocus () {
    this.setState({ userInput: '' })
  }

  doSubmit () {
    const pattern = this.state.userInput
    if (!pattern) return

    if (process.env.BROWSER) {
      this.props.searchPost(pattern, 0, 10, true)
      this.releaseTimeout =
        setTimeout(() => this.context.history.replaceState({}, '/search'), 500)
    }

    React.findDOMNode(this.refs.search).blur()
  }

  handleSubmit (event) {
    if (event.which === 13) {
      event.preventDefault()
      this.doSubmit()
    }
  }

  handleSearchSubmit (event) {
    event.preventDefault()
    this.doSubmit()
  }

  render () {
    const { dispatch, auth } = this.props

    const Translate = require('react-translate-component')
    const TranslateProps = React.createFactory(Translate)

    const searchProps = {
      component: 'input',
      type: 'search',
      name: 'q',
      ref: 'search',
      scope: 'search_input',
      attributes: {
        placeholder: 'placeholder',
        title: 'tooltip'
      }
    }

    let AuthLink
    if (!auth.token) {
      AuthLink = (
        <Link activeClassName="active" to="/login" className="item">
          <Translate content="header.login" />
        </Link>
      )
    } else {
      AuthLink = (
        <Link activeClassName="active" to="/logout" className="item">
          <Translate content="header.logout" />
        </Link>
      )
    }

    let ChangePasswordLink
    if (auth.token) {
      ChangePasswordLink = (
        <Link activeClassName="active" to="/password" className="item">
          <Translate content="header.password" />
        </Link>
      )
    }

    let ManageLink
    if (auth.token) {
      ManageLink = (
        <Link activeClassName="active" to="/manage" className="item">
          <Translate content="header.manage" />
        </Link>
      )
    }

    return (

            <Link activeClassName="active" to="/home" className="item">
              <Translate content="header.home" />
            </Link>
            <Link activeClassName="active" to="/w" className="item">
              <Translate content="header.wall" />
            </Link>
            <Link activeClassName="active" to="/post" className="item">
              <Translate content="header.post" />
            </Link>
            {ChangePasswordLink}
            {ManageLink}

            {AuthLink}
            <LocaleSwitcher dispatch={dispatch} />

              <form
                action=""
                method="post"
                onSubmit={::this.handleSearchSubmit}>

                  <input
                    type="search"
                    ref="search"
                    onChange={::this.handleChange}
                    onFocus={::this.handleFocus}
                    onKeyDown={::this.handleSubmit}
                    value={this.state.userInput}
                  />

                  <input type="submit" className="hide-submit" />

              </form>

            <Link activeClassName="active" to="/wall/today" className="item left">
              <Translate content="header.home" />
            </Link>
            <Link activeClassName="active" to="/post" className="item">
              <Translate content="header.post" />
            </Link>
            <LocaleSwitcher dispatch={dispatch} />
            {AuthLink}

    )
  }
}
<|endoftext|>