<commit_before>import React, { Component } from 'react';
import { defaultRanges, Calendar, DateRange } from '../../../lib/';
import Section from 'components/Section';
import moment from 'moment';

import 'normalize.css';
import 'styles/global'
import styles from 'styles/main';

export default class Main extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      'rangePicker' : {},
      'linked' : {},
      'datePicker' : null,
      'firstDayOfWeek' : null,
      'predefined' : {},
    }
  }

  handleChange(which, payload) {
    this.setState({
      [which] : payload
    });
  }

  render() {
    const { rangePicker, linked, datePicker, firstDayOfWeek, predefined} = this.state;
    const format = 'dddd, D MMMM YYYY';

    return (

React-date-range

            <input
              type='text'
              readOnly
              value={ rangePicker['startDate'] && rangePicker['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ rangePicker['endDate'] && rangePicker['endDate'].format(format).toString() }
            />

          <DateRange
            startDate='10/11/2015'
            endDate={ now => {
              return '11/12/2015';
            }}
            onInit={ this.handleChange.bind(this, 'rangePicker') }
            onChange={ this.handleChange.bind(this, 'rangePicker') }
            maxDate={ moment().startOf('day').add(2, 'months') }
            minDate={ moment().startOf('day').add(-2, 'months') }
          />

            <input
              type='text'
              readOnly
              value={ linked['startDate'] && linked['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ linked['endDate'] && linked['endDate'].format(format).toString() }
            />

          <DateRange
            startDate={ now => {
              return '9/10/2015';
            }}
            endDate={ now => {
              return '13/11/2015';
            }}
            linkedCalendars={ true }
            onInit={ this.handleChange.bind(this, 'linked') }
            onChange={ this.handleChange.bind(this, 'linked') }
          />

            <input
              type='text'
              readOnly
              value={ datePicker && datePicker.format(format).toString() }
            />

          <Calendar
            date={ now => { return now.add(-4, 'days') } }
            onInit={ this.handleChange.bind(this, 'datePicker') }
            onChange={ this.handleChange.bind(this, 'datePicker') }
          />

            <input
              type='text'
              readOnly
              value={ firstDayOfWeek && firstDayOfWeek.format(format).toString() }
            />

          <Calendar
            firstDayOfWeek={ 1 }
            date={ now => { return now.add(-4, 'days') } }
            onInit={ this.handleChange.bind(this, 'firstDayOfWeek') }
            onChange={ this.handleChange.bind(this, 'firstDayOfWeek') }
          />

            <input
              type='text'
              readOnly
              value={ predefined['startDate'] && predefined['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ predefined['endDate'] && predefined['endDate'].format(format).toString() }
            />

          <DateRange
            linkedCalendars={ true }
            ranges={ defaultRanges }
            onInit={ this.handleChange.bind(this, 'predefined') }
            onChange={ this.handleChange.bind(this, 'predefined') }
            theme={{
              Calendar : { width: 200 },
              PredefinedRanges : { marginLeft: 10, marginTop: 10 }
            }}
          />

          <DateRange
            linkedCalendars={ true }
            theme={{
              DateRange      : {
                background   : '#ffffff'
              },
              Calendar       : {
                background   : 'transparent',
                color        : '#95a5a6',
              },
              MonthAndYear   : {
                background   : '#e74c3c',
                color        : '#9e3024'
              },
              MonthButton    : {
                background   : '#c0392b'
              },
              MonthArrowPrev : {
                borderRightColor : '#d96659',
              },
              MonthArrowNext : {
                borderLeftColor : '#d96659',
              },
              Weekday        : {
                background   : '#e74c3c',
                color        : '#9e3024'
              },
              Day            : {
                transition   : 'transform .1s ease, box-shadow .1s ease, background .1s ease'
              },
              DaySelected    : {
                background   : '#8e44ad'
              },
              DayActive    : {
                background   : '#8e44ad',
                boxShadow    : 'none'
              },
              DayInRange     : {
                background   : '#9b59b6',
                color        : '#fff'
              },
              DayHover       : {
                background   : '#ffffff',
                color        : '#7f8c8d',
                transform    : 'scale(1.1) translateY(-10%)',
                boxShadow    : '0 2px 4px rgba(0, 0, 0, 0.4)'
              }
            }}
          />

    )
  }
}
<commit_msg>Remove min max test from main example<commit_after>import React, { Component } from 'react';
import { defaultRanges, Calendar, DateRange } from '../../../lib/';
import Section from 'components/Section';
import moment from 'moment';

import 'normalize.css';
import 'styles/global'
import styles from 'styles/main';

export default class Main extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      'rangePicker' : {},
      'linked' : {},
      'datePicker' : null,
      'firstDayOfWeek' : null,
      'predefined' : {},
    }
  }

  handleChange(which, payload) {
    this.setState({
      [which] : payload
    });
  }

  render() {
    const { rangePicker, linked, datePicker, firstDayOfWeek, predefined} = this.state;
    const format = 'dddd, D MMMM YYYY';

    return (

React-date-range

            <input
              type='text'
              readOnly
              value={ rangePicker['startDate'] && rangePicker['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ rangePicker['endDate'] && rangePicker['endDate'].format(format).toString() }
            />

          <DateRange
            startDate='10/11/2015'
            endDate={ now => {
              return '11/12/2015';
            }}
            onInit={ this.handleChange.bind(this, 'rangePicker') }
            onChange={ this.handleChange.bind(this, 'rangePicker') }
          />

            <input
              type='text'
              readOnly
              value={ linked['startDate'] && linked['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ linked['endDate'] && linked['endDate'].format(format).toString() }
            />

          <DateRange
            startDate={ now => {
              return '9/10/2015';
            }}
            endDate={ now => {
              return '13/11/2015';
            }}
            linkedCalendars={ true }
            onInit={ this.handleChange.bind(this, 'linked') }
            onChange={ this.handleChange.bind(this, 'linked') }
          />

            <input
              type='text'
              readOnly
              value={ datePicker && datePicker.format(format).toString() }
            />

          <Calendar
            date={ now => { return now.add(-4, 'days') } }
            onInit={ this.handleChange.bind(this, 'datePicker') }
            onChange={ this.handleChange.bind(this, 'datePicker') }
          />

            <input
              type='text'
              readOnly
              value={ firstDayOfWeek && firstDayOfWeek.format(format).toString() }
            />

          <Calendar
            firstDayOfWeek={ 1 }
            date={ now => { return now.add(-4, 'days') } }
            onInit={ this.handleChange.bind(this, 'firstDayOfWeek') }
            onChange={ this.handleChange.bind(this, 'firstDayOfWeek') }
          />

            <input
              type='text'
              readOnly
              value={ predefined['startDate'] && predefined['startDate'].format(format).toString() }
            />
            <input
              type='text'
              readOnly
              value={ predefined['endDate'] && predefined['endDate'].format(format).toString() }
            />

          <DateRange
            linkedCalendars={ true }
            ranges={ defaultRanges }
            onInit={ this.handleChange.bind(this, 'predefined') }
            onChange={ this.handleChange.bind(this, 'predefined') }
            theme={{
              Calendar : { width: 200 },
              PredefinedRanges : { marginLeft: 10, marginTop: 10 }
            }}
          />

          <DateRange
            linkedCalendars={ true }
            theme={{
              DateRange      : {
                background   : '#ffffff'
              },
              Calendar       : {
                background   : 'transparent',
                color        : '#95a5a6',
              },
              MonthAndYear   : {
                background   : '#e74c3c',
                color        : '#9e3024'
              },
              MonthButton    : {
                background   : '#c0392b'
              },
              MonthArrowPrev : {
                borderRightColor : '#d96659',
              },
              MonthArrowNext : {
                borderLeftColor : '#d96659',
              },
              Weekday        : {
                background   : '#e74c3c',
                color        : '#9e3024'
              },
              Day            : {
                transition   : 'transform .1s ease, box-shadow .1s ease, background .1s ease'
              },
              DaySelected    : {
                background   : '#8e44ad'
              },
              DayActive    : {
                background   : '#8e44ad',
                boxShadow    : 'none'
              },
              DayInRange     : {
                background   : '#9b59b6',
                color        : '#fff'
              },
              DayHover       : {
                background   : '#ffffff',
                color        : '#7f8c8d',
                transform    : 'scale(1.1) translateY(-10%)',
                boxShadow    : '0 2px 4px rgba(0, 0, 0, 0.4)'
              }
            }}
          />

    )
  }
}
<|endoftext|>


<commit_before>/**
 * 第二版 使用定时器
 */
var count = 1;
var container = document.getElementById('container');

function getUserAction() {
    container.innerHTML = count++;
};

container.onmousemove = throttle(getUserAction, 3000);

function throttle(func, wait) {
    var timeout;
    var previous = 0;

    return function() {
        context = this;
        args = arguments;
        if (!timeout) {
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}<commit_msg>Update throttle2.js<commit_after>/**
 * 第二版 使用定时器
 */
var count = 1;
var container = document.getElementById('container');

function getUserAction() {
    container.innerHTML = count++;
};

container.onmousemove = throttle(getUserAction, 3000);

function throttle(func, wait) {
    var timeout;

    return function() {
        var context = this;
        var args = arguments;
        if (!timeout) {
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(context, args)
            }, wait)
        }
    }
}
<|endoftext|>


<commit_before>"use strict";

var Brig = require('../');

var brig = new Brig();

// Create Engine
var engine = new brig.QmlEngine();
var rootContext = engine.rootContext();
var context = new brig.QmlContext(rootContext);

// Loading QML file
var component = new brig.QmlComponent(engine, 'application.qml');
var item = component.create(context);

// Set window title
item.setProperty('title', 'Helloooooo Brig');

// Get all properties
var keys = item.getPropertyNames();
for (var index in keys) {
	var key = keys[index];
	console.log(key, ":", item.getProperty(key));
}
<commit_msg>Correct module path which was required by example<commit_after>"use strict";

var Brig = require('../../');

var brig = new Brig();

// Create Engine
var engine = new brig.QmlEngine();
var rootContext = engine.rootContext();
var context = new brig.QmlContext(rootContext);

// Loading QML file
var component = new brig.QmlComponent(engine, 'application.qml');
var item = component.create(context);

// Set window title
item.setProperty('title', 'Helloooooo Brig');

// Get all properties
var keys = item.getPropertyNames();
for (var index in keys) {
	var key = keys[index];
	console.log(key, ":", item.getProperty(key));
}
<|endoftext|>


<commit_before>var server = require('../server');
var should = require('should');

var request = require('supertest');

describe('Register', function() {

	describe('GET /grid/api/proxy register', function() {

		it('receives a 400 bad request when sending invalid data during registration', function(done) {
		  	request(server)
				.post('/grid/register')
				.send("nothing")
				.end(function(err, res) {
					res.statusCode.should.equal(400);
					res.text.should.equal("Invalid parameters");
					done();
				});
		});

		it('should be possible to register the same node twice', function(done) {
			var postData = '{"class":"org.openqa.grid.common.RegistrationRequest","capabilities":[{"platform":"WINDOWS","seleniumProtocol":"Selenium","browserName":"iexplore","maxInstances":1,"version":"9","alias":"FF9"}],"configuration":{"port":5559,"nodeConfig":"config.json","host":"10.0.1.15","cleanUpCycle":10000,"browserTimeout":20000,"hubHost":"10.0.1.6","registerCycle":5000,"debug":"","hub":"http://10.0.1.6:4444/grid/register","log":"test.log","url":"http://10.0.1.15:5559","remoteHost":"http://10.0.1.15:5559","register":true,"proxy":"org.openqa.grid.selenium.proxy.DefaultRemoteProxy","maxSession":1,"role":"node","hubPort":4444}}';

			request(server)
				.post('/grid/register')
				.send(postData)
				.end(function(err, res) {
					res.statusCode.should.equal(200);
					res.text.should.equal("OK - Welcome");

					request(server)
						.post('/grid/register')
						.send(postData)
						.end(function(err, res) {
							res.statusCode.should.equal(200);
							res.text.should.equal("OK - Welcome");
							done();
						});
				});
		});
	});
});
<commit_msg>Make register_test work<commit_after>var server = require('../server'),
    should = require('should'),
    request = require('supertest');

describe('Register', function() {

    describe('GET /grid/api/proxy register', function() {

        var app;
        before(function() {
            app = server();
        });

        after(function() {
            app.close();
        });

        it('receives a 400 bad request when sending invalid data during registration', function(done) {
            request(app)
                .post('/grid/register')
                .send('nothing')
                .end(function(err, res) {
                    res.statusCode.should.equal(400);
                    res.text.should.equal('Invalid parameters');
                    done();
                });
        });

        it('should be possible to register the same node twice', function(done) {
            var postData = '{"class":"org.openqa.grid.common.RegistrationRequest","capabilities":[{"platform":"WINDOWS","seleniumProtocol":"Selenium","browserName":"iexplore","maxInstances":1,"version":"9","alias":"FF9"}],"configuration":{"port":5559,"nodeConfig":"config.json","host":"10.0.1.15","cleanUpCycle":10000,"browserTimeout":20000,"hubHost":"10.0.1.6","registerCycle":5000,"debug":"","hub":"http://10.0.1.6:4444/grid/register","log":"test.log","url":"http://10.0.1.15:5559","remoteHost":"http://10.0.1.15:5559","register":true,"proxy":"org.openqa.grid.selenium.proxy.DefaultRemoteProxy","maxSession":1,"role":"node","hubPort":4444}}';

            request(app)
                .post('/grid/register')
                .send(postData)
                .end(function(err, res) {
                    res.statusCode.should.equal(200);
                    res.text.should.equal('OK - Welcome');

                    request(app)
                        .post('/grid/register')
                        .send(postData)
                        .end(function(err, res) {
                            res.statusCode.should.equal(200);
                            res.text.should.equal('OK - Welcome');
                            done();
                        });
                });
        });
    });
});
<|endoftext|>


<commit_before>var
	config = require('../config'),
	gulp = require('gulp'),
	paths = require('../utils/paths'),

	browserSync = require('browser-sync'),

	task = function() {
		var options = config.tasks.watch.browserSync;

		config.tasks.watch.tasks.forEach(function(name) {
			options.files.push(paths(name).dest);
		});

		browserSync.init(options);

		config.tasks.watch.tasks.forEach(function(name) {
			gulp.watch(paths(name).src, gulp.parallel(name));
		});
	};

gulp.task('watch', task);
module.exports = task;
<commit_msg>Updates watch task<commit_after>var
	config = require('../config'),
	gulp = require('gulp'),
	paths = require('../utils/paths'),

	browserSync = require('browser-sync'),

	task = function() {
		var options = config.tasks.watch.browserSync;

		config.tasks.watch.tasks.forEach(function(name) {
			options.files.push(paths(name).dest);
		});

		browserSync.init(options);

		config.tasks.watch.tasks.forEach(function(name) {

			if (name === 'scripts') {

				config.tasks[name].files.forEach(function(file) {
					gulp.watch(
						paths(name).scripts(file.name),
						gulp.parallel('scripts.' + file.name)
					);
				});

			} else {

				gulp.watch(paths(name).src, gulp.parallel(name));

			}

		});
	};

gulp.task('watch', task);
module.exports = task;
<|endoftext|>


<commit_before>/**
 * amWiki-testing
 * by Tevin
 *
 * 简单发送ajax测试工具
 * 仅当页面存在“请求地址”、“请求类型”、“请求参数”三个h3标题时触发
 */

(function (win) {

    var Testing = function () {
        this.data = {
            //全局参数列队
            globalParams: [],
            //全局参数是否生效
            globalParamWorking: true
        };
        //请求数据
        this.request = {
            //请求地址
            url: '',
            //请求类型
            method: '',
            //请求参数
            params: [],
            //全局参数
            paramGlobal: []
        };
        //抓取页面成功才显示
        if (this.crawlContent()) {
            this.initPanel();
            this.useGlobalParam();
            this.bindAjaxSend();
        }
    };

    //抓取请求内容
    Testing.prototype.crawlContent = function () {
        var that = this;
        //抓取请求地址
        var $url = $('[name="请求地址"]').eq(0);  //地址title的描记
        if ($url.length == 0) {
            return false;
        } else {
            this.request.url = $url.parent().next().text().replace(/^\s+|\s+$/g, '');
            if (this.request.url.indexOf('/') == 0) {
                this.request.url = 'http://' + location.host + this.request.url;
            } else {
                this.request.url = 'http://' + location.host + '/' + this.request.url;
            }
        }
        //抓取请求类型
        var $method = $('[name="请求类型"]').eq(0);  //类型title的描记
        if ($method.length == 0) {
            return false;
        } else {
            this.request.method = $method.parent().next().text().replace(/^\s+|\s+$/g, '').toUpperCase();
            if (this.request.method != 'POST' && this.request.method != 'GET') {
                this.request.method = 'POST';
            }
        }
        //抓取请求参数
        var $param = $('[name="请求参数"]').eq(0);  //参数title的描记
        if ($param.length == 0) {
            return;
        } else {
            //不存在table直接无参数，存在table时开始解析
            if ($param.parent().next('table').length > 0) {
                $param.parent().next('table').find('tbody').find('tr').each(function () {
                    var $tds = $(this).find('td');
                    //抓取内容
                    var param = {
                        keyName: $tds.eq(0).text().replace(/^\s+|\s+$/g, ''),
                        valueType: $tds.eq(1).text().replace(/^\s+|\s+$/g, ''),
                        required: $tds.eq(2).text().replace(/^\s+|\s+$/g, ''),
                        describe: $tds.eq(3).text().replace(/^\s+|\s+$/g, ''),
                        default: $tds.eq(4).text().replace(/^\s+|\s+$/g, '')
                    };
                    //修正请求参数，正确键名才添加参数
                    if (param.keyName != '无' && param.keyName != '-' && param.keyName != '') {
                        //“必填”转换
                        if (param.required == '是' || param.required == 'yes' || param.required == 'true') {
                            param.required = 'required';
                        } else {
                            param.required = '';
                        }
                        //“默认值”转换
                        if (param.default == '-' || param.default == '无' || param.default == 'Null') {
                            param.default = '';
                        }
                        that.request.params.push(param);
                    }
                });
            }
        }
        return true;
    };

    //测试面板初始化
    Testing.prototype.initPanel = function () {
        var that = this;
        var $testingBox = $('#testingBox');  //测试面板
        var $view = $('#view');  //视图，md文档渲染处
        $testingBox.css('min-height', $view.height());
        //显示隐藏测试面板
        var $testingShow = $('
[测试接口]
');  //显示隐藏控制按钮
        $('#main').append($testingShow);
        $testingShow.on('click', function () {
            if ($testingShow.hasClass('on')) {
                $testingShow.removeClass('on').find('span').text('测试接口');
                $testingBox.hide();
                $view.show();
            } else {
                $testingShow.addClass('on').find('span').text('关闭测试');
                $testingBox.show();
                $view.hide();
            }
        });
        //清空所有普通参数的值
        var $testingParam = $('#testingParam');  //参数列表
        $('#testingBtnReset').on('click', function () {
            $testingParam.find('.testing-param-val').val('');
        });
        //新增一个参数
        $('#testingBtnAdd').on('click', function () {
            $testingParam.append(template.replace('{{describe}}', '新增参数')
                .replace('{{keyName}}', '')
                .replace('{{default}}', '')
                .replace('{{valueType}}', 'any-type')
                .replace('{{required}}', ''));
        });
        //填充参数列表数据
        $('#testingSendUrl').val(this.request.url).on('change', function () {
            that.request.url = $(this).val();
        });
        $('#testingSendType').on('change', function () {
            that.request.method = $(this).find("option:selected").text();
        }).find('option[value="' + this.request.method + '"]').prop('selected', true);
        var template = $('#templateFormList').text();  //单条参数模板
        if (this.request.params.length > 0) {
            for (var i = 0; i < this.request.params.length; i++) {
                $testingParam.append(template.replace('{{describe}}', this.request.params[i].describe)
                    .replace('{{keyName}}', this.request.params[i].keyName)
                    .replace('{{default}}', this.request.params[i].default)
                    .replace('{{valueType}}', this.request.params[i].valueType)
                    .replace('{{required}}', this.request.params[i].required));
            }
        } else {
            $testingParam.append('
无
');
        }
    };

    //全局参数模块
    Testing.prototype.useGlobalParam = function () {
        var that = this;
        this.data.globalParams = JSON.parse(localStorage['amWikiGlobalParam'] || '[]');  //全局参数
        var gParamTmpl = $('#templateGlobalParam').text();  //全局参数模板
        var $testingGlobalParam = $('#testingGlobalParam');  //全局参数显示容器
        var $testingGlobal = $('#testingGlobal');  //全局参数弹窗
        this.data.globalParamWorking = (localStorage['amWikiGParamWorking'] || 'on') == 'on';  //全局参数是否工作
        //显示弹窗
        $('#testingBtnGParam').on('click', function () {
            $testingGlobalParam.html('');
            that.data.globalParams = JSON.parse(localStorage['amWikiGlobalParam'] || '[]');
            if (that.data.globalParams.length == 0) {
                $testingGlobalParam.append('
无
');
            } else {
                for (var p = 0; p < that.data.globalParams.length; p++) {
                    $testingGlobalParam.append(gParamTmpl.replace('{{describe}}', that.data.globalParams[p].describe)
                        .replace('{{keyName}}', that.data.globalParams[p].keyName)
                        .replace('{{value}}', that.data.globalParams[p].value));
                }
            }
            $testingGlobal.show();
        });
        //基本操作
        $testingGlobal.on('click', function (e) {
            var $elm = $(e.target);
            //关闭
            if ($elm.hasClass('close') || $elm.hasClass('testing-global')) {
                $testingGlobal.hide();
            }
            //新增
            else if ($elm.hasClass('add')) {
                $testingGlobalParam.find('[data-type="empty"]').remove();
                $testingGlobalParam.append(gParamTmpl.replace('{{describe}}', '')
                    .replace('{{keyName}}', '')
                    .replace('{{value}}', ''));
            }
            //保存
            else if ($elm.hasClass('save')) {
                that.data.globalParams.length = 0;
                $testingGlobalParam.find('li').each(function (i, elment) {
                    var $inputs = $(this).find('input');
                    if ($inputs.eq(1).val()) {
                        that.data.globalParams.push({
                            describe: $inputs.eq(0).val(),
                            keyName: $inputs.eq(1).val(),
                            value: $inputs.eq(2).val()
                        });
                    }
                });
                localStorage['amWikiGlobalParam'] = JSON.stringify(that.data.globalParams);
                $testingGlobal.hide();
            }
        });
        //删除参数
        $testingGlobalParam.on('click', 'i', function () {
            $(this).parent().remove();
            if ($testingGlobalParam.find('li').length == 0) {
                $testingGlobalParam.append('
无
');
            }
        });
        $('#testingGlobalWorking').on('click', function () {
            if (that.data.globalParamWorking) {
                that.data.globalParamWorking = false;
                localStorage['amWikiGParamWorking'] = 'off';
                $(this).addClass('off');
            } else {
                that.data.globalParamWorking = true;
                localStorage['amWikiGParamWorking'] = 'on';
                $(this).removeClass('off');
            }
        }).addClass(this.data.globalParamWorking ? '' : 'off');
    };

    //发送请求
    Testing.prototype.bindAjaxSend = function () {
        var that = this;
        var frame = $('#testingResponse')[0];
        var $duration = $('#testingDuration');  //耗时输出
        var $loading = $('#testingLoading');
        var $testingParam = $('#testingParam');  //参数列表
        $('#testingBtnSend').on('click', function () {
            $duration.text('');
            var realParam = {};  //合并参数列表
            var $this = $(this);
            //从面板获取最新(可能已修改)接口参数
            if ($testingParam.find('input').length > 0) {
                $testingParam.find('li').each(function () {
                    var $this = $(this);
                    realParam[$this.find('.testing-param-key').val()] = $this.find('.testing-param-val').val();
                });
            }
            //全局参数
            if (that.data.globalParams.length > 0 && that.data.globalParamWorking) {
                for (var i = 0; i < that.data.globalParams.length; i++) {
                    realParam[that.data.globalParams[i].keyName] = that.data.globalParams[i].value;
                }
            }
            frame.contentWindow.location.reload();  //刷新iframe以便重新输出内容
            $loading.show();
            var startTime = Date.now();
            $.ajax({
                type: that.request.method,
                url: that.request.url,
                data: realParam,
                dataType: 'text',
                success: function (data) {
                    $loading.hide();
                    $duration.text('耗时：' + parseFloat(Date.now() - startTime).toLocaleString() + ' ms');
                    var $frameBody = $(frame.contentWindow.document).find('body');
                    $frameBody.css('wordBreak', 'break-all');
                    if (/^\s*\{[\s\S]*\}\s*$/.test(data)) {
                        $frameBody[0].innerHTML = '

';
                        //json格式化输出
                        $frameBody.find('pre').text(that.formatJson(data));
                    } else {
                        $frameBody[0].innerHTML = data.replace(/<!(doctype|DOCTYPE)\s+(html|HTML)>/, '');
                    }
                    setTimeout(function () {
                        $(frame).height($frameBody.height());
                    }, 100);
                },
                error: function (xhr, textStatus) {
                    $loading.hide();
                    $duration.text('耗时：' + parseFloat(Date.now() - startTime).toLocaleString() + ' ms');
                    var $frameBody = $(frame.contentWindow.document).find('body');
                    $frameBody.css('wordBreak', 'break-all');
                    var html = '
HTTP Status: ' +
                        xhr.status + ' ' + xhr.statusText + '
';
                    //根据readyState简单判断跨域
                    if (xhr.readyState == 0) {
                        html += '
请求未发送！可能是因为：
' +
                            '
请求了跨域地址
' +
                            '
接口被302重定向到跨域地址
' +
                            '
其他原因
' +
                            '

';
                        $frameBody[0].innerHTML = html;
                    }
                    //不跨域且为json
                    else if (/^\s*\{[\s\S]*\}\s*$/.test(xhr.responseText)) {
                        html += '

';
                        $frameBody[0].innerHTML = html;
                        //json格式化输出
                        $frameBody.find('pre').text(that.formatJson(xhr.responseText));
                    }
                    //其他不跨域
                    else {
                        html += xhr.responseText.replace(/<!(doctype|DOCTYPE)\s+(html|HTML)>/, '');
                        $frameBody[0].innerHTML = html;
                    }
                    setTimeout(function () {
                        $(frame).height($frameBody.height());
                    }, 100);
                }
            });
        });
    };

    //json格式化
    Testing.prototype.formatJson = function (str) {
        var json = decodeURI(str);
        var reg = null,
            formatted = '',
            pad = 0,
            PADDING = '    ';
        var options = {};
        // remove newline where '{' or '[' follows ':'
        options.newlineAfterColonIfBeforeBraceOrBracket = options.newlineAfterColonIfBeforeBraceOrBracket === true;
        // use a space after a colon
        options.spaceAfterColon = options.spaceAfterColon !== false;
        // begin formatting...
        if (typeof json !== 'string') {
            json = JSON.stringify(json);
        } else {
            json = JSON.parse(json);
            json = JSON.stringify(json);
        }
        // add newline before and after curly braces
        reg = /([\{\}])/g;
        json = json.replace(reg, '\r\n$1\r\n');
        // add newline before and after square brackets
        reg = /([\[\]])/g;
        json = json.replace(reg, '\r\n$1\r\n');
        // add newline after comma
        reg = /(\,)/g;
        json = json.replace(reg, '$1\r\n');
        // remove multiple newlines
        reg = /(\r\n\r\n)/g;
        json = json.replace(reg, '\r\n');
        // remove newlines before commas
        reg = /\r\n\,/g;
        json = json.replace(reg, ',');
        // optional formatting...
        if (!options.newlineAfterColonIfBeforeBraceOrBracket) {
            reg = /\:\r\n\{/g;
            json = json.replace(reg, ':{');
            reg = /\:\r\n\[/g;
            json = json.replace(reg, ':[');
        }
        if (options.spaceAfterColon) {
            reg = /"\s*\:/g;
            json = json.replace(reg, '": ');
        }
        $.each(json.split('\r\n'), function (index, node) {
            var i = 0,
                indent = 0,
                padding = '';
            if (node.match(/\{$/) || node.match(/\[$/)) {
                indent = 1;
            } else if (node.match(/\}/) || node.match(/\]/)) {
                if (pad !== 0) {
                    pad -= 1;
                }
            } else {
                indent = 0;
            }
            for (i = 0; i < pad; i++) {
                padding += PADDING;
            }
            formatted += padding + node + '\r\n';
            pad += indent;
        });
        return formatted;
    };

    return win.Testing = Testing;

})(window);<commit_msg>web端ajax测试，接口地址允许带http头，强化跨域提示<commit_after>/**
 * amWiki-testing
 * by Tevin
 *
 * 简单发送ajax测试工具
 * 仅当页面存在“请求地址”、“请求类型”、“请求参数”三个h3标题时触发
 */

(function (win) {

    var Testing = function () {
        this.data = {
            //全局参数列队
            globalParams: [],
            //全局参数是否生效
            globalParamWorking: true
        };
        //请求数据
        this.request = {
            //请求地址
            url: '',
            //请求类型
            method: '',
            //请求参数
            params: [],
            //全局参数
            paramGlobal: []
        };
        //抓取页面成功才显示
        if (this.crawlContent()) {
            this.initPanel();
            this.useGlobalParam();
            this.bindAjaxSend();
        }
    };

    //抓取请求内容
    Testing.prototype.crawlContent = function () {
        var that = this;
        //抓取请求地址
        var $url = $('[name="请求地址"]').eq(0);  //地址title的描记
        if ($url.length == 0) {
            return false;
        } else {
            this.request.url = $url.parent().next().text().replace(/^\s+|\s+$/g, '');
            if (this.request.url.indexOf('http') < 0) {
                if (this.request.url.indexOf('/') == 0) {
                    this.request.url = 'http://' + location.host + this.request.url;
                } else {
                    this.request.url = 'http://' + location.host + '/' + this.request.url;
                }
            }
        }
        //抓取请求类型
        var $method = $('[name="请求类型"]').eq(0);  //类型title的描记
        if ($method.length == 0) {
            return false;
        } else {
            this.request.method = $method.parent().next().text().replace(/^\s+|\s+$/g, '').toUpperCase();
            if (this.request.method != 'POST' && this.request.method != 'GET') {
                this.request.method = 'POST';
            }
        }
        //抓取请求参数
        var $param = $('[name="请求参数"]').eq(0);  //参数title的描记
        if ($param.length == 0) {
            return;
        } else {
            //不存在table直接无参数，存在table时开始解析
            if ($param.parent().next('table').length > 0) {
                $param.parent().next('table').find('tbody').find('tr').each(function () {
                    var $tds = $(this).find('td');
                    //抓取内容
                    var param = {
                        keyName: $tds.eq(0).text().replace(/^\s+|\s+$/g, ''),
                        valueType: $tds.eq(1).text().replace(/^\s+|\s+$/g, ''),
                        required: $tds.eq(2).text().replace(/^\s+|\s+$/g, ''),
                        describe: $tds.eq(3).text().replace(/^\s+|\s+$/g, ''),
                        default: $tds.eq(4).text().replace(/^\s+|\s+$/g, '')
                    };
                    //修正请求参数，正确键名才添加参数
                    if (param.keyName != '无' && param.keyName != '-' && param.keyName != '') {
                        //“必填”转换
                        if (param.required == '是' || param.required == 'yes' || param.required == 'true') {
                            param.required = 'required';
                        } else {
                            param.required = '';
                        }
                        //“默认值”转换
                        if (param.default == '-' || param.default == '无' || param.default == 'Null') {
                            param.default = '';
                        }
                        that.request.params.push(param);
                    }
                });
            }
        }
        return true;
    };

    //测试面板初始化
    Testing.prototype.initPanel = function () {
        var that = this;
        var $testingBox = $('#testingBox');  //测试面板
        var $view = $('#view');  //视图，md文档渲染处
        $testingBox.css('min-height', $view.height());
        //显示隐藏测试面板
        var $testingShow = $('
[测试接口]
');  //显示隐藏控制按钮
        $('#main').append($testingShow);
        $testingShow.on('click', function () {
            if ($testingShow.hasClass('on')) {
                $testingShow.removeClass('on').find('span').text('测试接口');
                $testingBox.hide();
                $view.show();
            } else {
                $testingShow.addClass('on').find('span').text('关闭测试');
                $testingBox.show();
                $view.hide();
            }
        });
        //清空所有普通参数的值
        var $testingParam = $('#testingParam');  //参数列表
        $('#testingBtnReset').on('click', function () {
            $testingParam.find('.testing-param-val').val('');
        });
        //新增一个参数
        $('#testingBtnAdd').on('click', function () {
            $testingParam.append(template.replace('{{describe}}', '新增参数')
                .replace('{{keyName}}', '')
                .replace('{{default}}', '')
                .replace('{{valueType}}', 'any-type')
                .replace('{{required}}', ''));
        });
        //填充参数列表数据
        $('#testingSendUrl').val(this.request.url).on('change', function () {
            that.request.url = $(this).val();
        });
        $('#testingSendType').on('change', function () {
            that.request.method = $(this).find("option:selected").text();
        }).find('option[value="' + this.request.method + '"]').prop('selected', true);
        var template = $('#templateFormList').text();  //单条参数模板
        if (this.request.params.length > 0) {
            for (var i = 0; i < this.request.params.length; i++) {
                $testingParam.append(template.replace('{{describe}}', this.request.params[i].describe)
                    .replace('{{keyName}}', this.request.params[i].keyName)
                    .replace('{{default}}', this.request.params[i].default)
                    .replace('{{valueType}}', this.request.params[i].valueType)
                    .replace('{{required}}', this.request.params[i].required));
            }
        } else {
            $testingParam.append('
无
');
        }
    };

    //全局参数模块
    Testing.prototype.useGlobalParam = function () {
        var that = this;
        this.data.globalParams = JSON.parse(localStorage['amWikiGlobalParam'] || '[]');  //全局参数
        var gParamTmpl = $('#templateGlobalParam').text();  //全局参数模板
        var $testingGlobalParam = $('#testingGlobalParam');  //全局参数显示容器
        var $testingGlobal = $('#testingGlobal');  //全局参数弹窗
        this.data.globalParamWorking = (localStorage['amWikiGParamWorking'] || 'on') == 'on';  //全局参数是否工作
        //显示弹窗
        $('#testingBtnGParam').on('click', function () {
            $testingGlobalParam.html('');
            that.data.globalParams = JSON.parse(localStorage['amWikiGlobalParam'] || '[]');
            if (that.data.globalParams.length == 0) {
                $testingGlobalParam.append('
无
');
            } else {
                for (var p = 0; p < that.data.globalParams.length; p++) {
                    $testingGlobalParam.append(gParamTmpl.replace('{{describe}}', that.data.globalParams[p].describe)
                        .replace('{{keyName}}', that.data.globalParams[p].keyName)
                        .replace('{{value}}', that.data.globalParams[p].value));
                }
            }
            $testingGlobal.show();
        });
        //基本操作
        $testingGlobal.on('click', function (e) {
            var $elm = $(e.target);
            //关闭
            if ($elm.hasClass('close') || $elm.hasClass('testing-global')) {
                $testingGlobal.hide();
            }
            //新增
            else if ($elm.hasClass('add')) {
                $testingGlobalParam.find('[data-type="empty"]').remove();
                $testingGlobalParam.append(gParamTmpl.replace('{{describe}}', '')
                    .replace('{{keyName}}', '')
                    .replace('{{value}}', ''));
            }
            //保存
            else if ($elm.hasClass('save')) {
                that.data.globalParams.length = 0;
                $testingGlobalParam.find('li').each(function (i, elment) {
                    var $inputs = $(this).find('input');
                    if ($inputs.eq(1).val()) {
                        that.data.globalParams.push({
                            describe: $inputs.eq(0).val(),
                            keyName: $inputs.eq(1).val(),
                            value: $inputs.eq(2).val()
                        });
                    }
                });
                localStorage['amWikiGlobalParam'] = JSON.stringify(that.data.globalParams);
                $testingGlobal.hide();
            }
        });
        //删除参数
        $testingGlobalParam.on('click', 'i', function () {
            $(this).parent().remove();
            if ($testingGlobalParam.find('li').length == 0) {
                $testingGlobalParam.append('
无
');
            }
        });
        $('#testingGlobalWorking').on('click', function () {
            if (that.data.globalParamWorking) {
                that.data.globalParamWorking = false;
                localStorage['amWikiGParamWorking'] = 'off';
                $(this).addClass('off');
            } else {
                that.data.globalParamWorking = true;
                localStorage['amWikiGParamWorking'] = 'on';
                $(this).removeClass('off');
            }
        }).addClass(this.data.globalParamWorking ? '' : 'off');
    };

    //发送请求
    Testing.prototype.bindAjaxSend = function () {
        var that = this;
        var frame = $('#testingResponse')[0];
        var $duration = $('#testingDuration');  //耗时输出
        var $loading = $('#testingLoading');
        var $testingParam = $('#testingParam');  //参数列表
        $('#testingBtnSend').on('click', function () {
            $duration.text('');
            var realParam = {};  //合并参数列表
            var $this = $(this);
            //从面板获取最新(可能已修改)接口参数
            if ($testingParam.find('input').length > 0) {
                $testingParam.find('li').each(function () {
                    var $this = $(this);
                    realParam[$this.find('.testing-param-key').val()] = $this.find('.testing-param-val').val();
                });
            }
            //全局参数
            if (that.data.globalParams.length > 0 && that.data.globalParamWorking) {
                for (var i = 0; i < that.data.globalParams.length; i++) {
                    realParam[that.data.globalParams[i].keyName] = that.data.globalParams[i].value;
                }
            }
            frame.contentWindow.location.reload();  //刷新iframe以便重新输出内容
            $loading.show();
            var startTime = Date.now();
            $.ajax({
                type: that.request.method,
                url: that.request.url,
                data: realParam,
                dataType: 'text',
                success: function (data) {
                    $loading.hide();
                    $duration.text('耗时：' + parseFloat(Date.now() - startTime).toLocaleString() + ' ms');
                    var $frameBody = $(frame.contentWindow.document).find('body');
                    $frameBody.css('wordBreak', 'break-all');
                    if (/^\s*\{[\s\S]*\}\s*$/.test(data)) {
                        $frameBody[0].innerHTML = '

';
                        //json格式化输出
                        $frameBody.find('pre').text(that.formatJson(data));
                    } else {
                        $frameBody[0].innerHTML = data.replace(/<!(doctype|DOCTYPE)\s+(html|HTML)>/, '');
                    }
                    setTimeout(function () {
                        $(frame).height($frameBody.height());
                    }, 100);
                },
                error: function (xhr, textStatus) {
                    $loading.hide();
                    $duration.text('耗时：' + parseFloat(Date.now() - startTime).toLocaleString() + ' ms');
                    var $frameBody = $(frame.contentWindow.document).find('body');
                    $frameBody.css('wordBreak', 'break-all');
                    var html = '
HTTP Status: ' +
                        xhr.status + ' ' + xhr.statusText + '
';
                    //根据readyState简单判断跨域
                    if (xhr.readyState == 0) {
                        html += '
请求未发送！可能是因为：' +
                            '
' +
                            '
请求了跨域地址
' +
                            '
接口被302重定向到跨域地址
' +
                            '
其他原因
' +
                            '

';
                        $frameBody[0].innerHTML = html;
                    }
                    //不跨域且为json
                    else if (/^\s*\{[\s\S]*\}\s*$/.test(xhr.responseText)) {
                        html += '

';
                        $frameBody[0].innerHTML = html;
                        //json格式化输出
                        $frameBody.find('pre').text(that.formatJson(xhr.responseText));
                    }
                    //其他不跨域
                    else {
                        html += xhr.responseText.replace(/<!(doctype|DOCTYPE)\s+(html|HTML)>/, '');
                        $frameBody[0].innerHTML = html;
                    }
                    setTimeout(function () {
                        $(frame).height($frameBody.height());
                    }, 100);
                }
            });
        });
    };

    //json格式化
    Testing.prototype.formatJson = function (str) {
        var json = decodeURI(str);
        var reg = null,
            formatted = '',
            pad = 0,
            PADDING = '    ';
        var options = {};
        // remove newline where '{' or '[' follows ':'
        options.newlineAfterColonIfBeforeBraceOrBracket = options.newlineAfterColonIfBeforeBraceOrBracket === true;
        // use a space after a colon
        options.spaceAfterColon = options.spaceAfterColon !== false;
        // begin formatting...
        if (typeof json !== 'string') {
            json = JSON.stringify(json);
        } else {
            json = JSON.parse(json);
            json = JSON.stringify(json);
        }
        // add newline before and after curly braces
        reg = /([\{\}])/g;
        json = json.replace(reg, '\r\n$1\r\n');
        // add newline before and after square brackets
        reg = /([\[\]])/g;
        json = json.replace(reg, '\r\n$1\r\n');
        // add newline after comma
        reg = /(\,)/g;
        json = json.replace(reg, '$1\r\n');
        // remove multiple newlines
        reg = /(\r\n\r\n)/g;
        json = json.replace(reg, '\r\n');
        // remove newlines before commas
        reg = /\r\n\,/g;
        json = json.replace(reg, ',');
        // optional formatting...
        if (!options.newlineAfterColonIfBeforeBraceOrBracket) {
            reg = /\:\r\n\{/g;
            json = json.replace(reg, ':{');
            reg = /\:\r\n\[/g;
            json = json.replace(reg, ':[');
        }
        if (options.spaceAfterColon) {
            reg = /"\s*\:/g;
            json = json.replace(reg, '": ');
        }
        $.each(json.split('\r\n'), function (index, node) {
            var i = 0,
                indent = 0,
                padding = '';
            if (node.match(/\{$/) || node.match(/\[$/)) {
                indent = 1;
            } else if (node.match(/\}/) || node.match(/\]/)) {
                if (pad !== 0) {
                    pad -= 1;
                }
            } else {
                indent = 0;
            }
            for (i = 0; i < pad; i++) {
                padding += PADDING;
            }
            formatted += padding + node + '\r\n';
            pad += indent;
        });
        return formatted;
    };

    return win.Testing = Testing;

})(window);<|endoftext|>


<commit_before>"use strict";

eas.sync.Tasks = {

    setThunderbirdItemFromWbxml: function (item, data, id, syncdata) {
    let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
    item.id = id;

    eas.sync.setItemBody(item, syncdata, data);
    eas.sync.setItemSubject(item, syncdata, data);
    eas.sync.setItemCategories(item, syncdata, data);
    eas.sync.setItemRecurrence(item, syncdata, data);

    let tzService = cal.getTimezoneService();
    if (data.DueDate && data.UtcDueDate) {
        //extract offset from EAS data
        let DueDate = new Date(data.DueDate);
        let UtcDueDate = new Date(data.UtcDueDate);
        let offset = (UtcDueDate.getTime() - DueDate.getTime())/60000;

        //timezone is identified by its offset
        let utc = cal.createDateTime(UtcDueDate.toBasicISOString()); //format "19800101T000000Z" - UTC
        item.dueDate = utc.getInTimezone(tzService.getTimezone(eas.offsets[offset]));
    }

    if (data.StartDate && data.UtcStartDate) {
        //extract offset from EAS data
        let StartDate = new Date(data.StartDate);
        let UtcStartDate = new Date(data.UtcStartDate);
        let offset = (UtcStartDate.getTime() - StartDate.getTime())/60000;

        //timezone is identified by its offset
        let utc = cal.createDateTime(UtcStartDate.toBasicISOString()); //format "19800101T000000Z" - UTC
        item.entryDate = utc.getInTimezone(tzService.getTimezone(eas.offsets[offset]));
    }

    eas.sync.mapEasPropertyToThunderbird ("Sensitivity", "CLASS", data, item);
    eas.sync.mapEasPropertyToThunderbird ("Importance", "PRIORITY", data, item);

   item.clearAlarms();
    if (data.ReminderSet && data.ReminderTime && data.UtcDueDate) {
        let UtcDueDate = tbSync.createDateTime(data.UtcDueDate);
        let UtcAlarmDate = tbSync.createDateTime(data.ReminderTime);
        let alarm = cal.createAlarm();
        alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START; //TB saves new alarms as offsets, so we add them as such as well
        alarm.offset = UtcAlarmDate.subtractDate(UtcDueDate);
        alarm.action = "DISPLAY";
        item.addAlarm(alarm);
    }

    /*

    Complete = [0]
    Complete = [1]
    DateCompleted = [2018-01-31T23:00:00.000Z] //UTC

        */

    },

    getWbxmlFromThunderbirdItem: function (item, syncdata) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
        let wbxml = tbSync.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage

        wbxml.atag("Subject", (item.title) ? tbSync.encode_utf8(item.title) : "");
        wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
        wbxml.atag("Importance", eas.sync.mapThunderbirdPropertyToEas("PRIORITY", "Importance", item));

        //tasks is using extended ISO 8601 (2019-01-18T00:00:00.000Z)  instead of basic (20190118T000000Z),
        //getIsoUtcString returns extended if true as second parameter is present
        wbxml.atag("UtcStartDate", tbSync.getIsoUtcString(item.entryDate, true));
        //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
        wbxml.atag("StartDate", tbSync.getIsoUtcString(item.entryDate, true, true));

        wbxml.atag("UtcDueDate", tbSync.getIsoUtcString(item.dueDate, true));
        wbxml.atag("DueDate", tbSync.getIsoUtcString(item.dueDate, true, true));

        wbxml.append(eas.sync.getItemCategories(item, syncdata));
        wbxml.append(eas.sync.getItemBody(item, syncdata));
        wbxml.append(eas.sync.getItemRecurrence(item, syncdata));

        let alarms = item.getAlarms({});
        if (alarms.length>0) {
            wbxml.atag("ReminderSet", "1");
            //create Date obj from dueDate by converting item.dueDate to extenden UTC ISO String, which can be parsed by Date
            let UtcDate = new Date(tbSync.getIsoUtcString(item.dueDate, true));
            //add offset
            UtcDate.setSeconds(UtcDate.getSeconds() + alarms[0].offset.inSeconds);
            wbxml.atag("ReminderTime", UtcDate.toISOString());
        } else {
            wbxml.atag("ReminderSet", "0");
        }

        return wbxml.getBytes();
    },
}
<commit_msg>working on task<commit_after>"use strict";

eas.sync.Tasks = {

    setThunderbirdItemFromWbxml: function (item, data, id, syncdata) {
    let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
    item.id = id;

    eas.sync.setItemBody(item, syncdata, data);
    eas.sync.setItemSubject(item, syncdata, data);
    eas.sync.setItemCategories(item, syncdata, data);
    eas.sync.setItemRecurrence(item, syncdata, data);

    let tzService = cal.getTimezoneService();
    if (data.DueDate && data.UtcDueDate) {
        //extract offset from EAS data
        let DueDate = new Date(data.DueDate);
        let UtcDueDate = new Date(data.UtcDueDate);
        let offset = (UtcDueDate.getTime() - DueDate.getTime())/60000;

        //timezone is identified by its offset
        let utc = cal.createDateTime(UtcDueDate.toBasicISOString()); //format "19800101T000000Z" - UTC
        item.dueDate = utc.getInTimezone(tzService.getTimezone(eas.offsets[offset]));
    }

    if (data.StartDate && data.UtcStartDate) {
        //extract offset from EAS data
        let StartDate = new Date(data.StartDate);
        let UtcStartDate = new Date(data.UtcStartDate);
        let offset = (UtcStartDate.getTime() - StartDate.getTime())/60000;

        //timezone is identified by its offset
        let utc = cal.createDateTime(UtcStartDate.toBasicISOString()); //format "19800101T000000Z" - UTC
        item.entryDate = utc.getInTimezone(tzService.getTimezone(eas.offsets[offset]));
    }

    eas.sync.mapEasPropertyToThunderbird ("Sensitivity", "CLASS", data, item);
    eas.sync.mapEasPropertyToThunderbird ("Importance", "PRIORITY", data, item);

    item.clearAlarms();
    if (data.ReminderSet && data.ReminderTime && data.UtcDueDate) {
        let UtcDueDate = tbSync.createDateTime(data.UtcDueDate);
        let UtcAlarmDate = tbSync.createDateTime(data.ReminderTime);
        let alarm = cal.createAlarm();
        alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START; //TB saves new alarms as offsets, so we add them as such as well
        alarm.offset = UtcAlarmDate.subtractDate(UtcDueDate);
        alarm.action = "DISPLAY";
        item.addAlarm(alarm);
    }

    //status/percentage cannot be mapped
    if (data.Complete) {
      if (data.Complete == "0") {
        item.isCompleted = false;
      } else {
        item.isCompleted = true;
        if (data.DateCompleted) item.completedDate = tbSync.createDateTime(data.DateCompleted);
      }
    }
    /*

    Complete = [0]
    Complete = [1]
    DateCompleted = [2018-01-31T23:00:00.000Z] //UTC

        */

    },

    getWbxmlFromThunderbirdItem: function (item, syncdata) {
        let asversion = tbSync.db.getAccountSetting(syncdata.account, "asversion");
        let wbxml = tbSync.wbxmltools.createWBXML("", syncdata.type); //init wbxml with "" and not with precodes, and set initial codepage

        wbxml.atag("Subject", (item.title) ? tbSync.encode_utf8(item.title) : "");
        wbxml.atag("Sensitivity", eas.sync.mapThunderbirdPropertyToEas("CLASS", "Sensitivity", item));
        wbxml.atag("Importance", eas.sync.mapThunderbirdPropertyToEas("PRIORITY", "Importance", item));

        //tasks is using extended ISO 8601 (2019-01-18T00:00:00.000Z)  instead of basic (20190118T000000Z),
        //getIsoUtcString returns extended if true as second parameter is present
        wbxml.atag("UtcStartDate", tbSync.getIsoUtcString(item.entryDate, true));
        //to fake the local time as UTC, getIsoUtcString needs the third parameter to be true
        wbxml.atag("StartDate", tbSync.getIsoUtcString(item.entryDate, true, true));

        wbxml.atag("UtcDueDate", tbSync.getIsoUtcString(item.dueDate, true));
        wbxml.atag("DueDate", tbSync.getIsoUtcString(item.dueDate, true, true));

        wbxml.append(eas.sync.getItemCategories(item, syncdata));
        wbxml.append(eas.sync.getItemBody(item, syncdata));
        wbxml.append(eas.sync.getItemRecurrence(item, syncdata));

        let alarms = item.getAlarms({});
        if (alarms.length>0) {
            wbxml.atag("ReminderSet", "1");
            //create Date obj from dueDate by converting item.dueDate to an extended UTC ISO string, which can be parsed by Date
            let UtcDate = new Date(tbSync.getIsoUtcString(item.dueDate, true));
            //add offset
            UtcDate.setSeconds(UtcDate.getSeconds() + alarms[0].offset.inSeconds);
            wbxml.atag("ReminderTime", UtcDate.toISOString());
        } else {
            wbxml.atag("ReminderSet", "0");
        }

        return wbxml.getBytes();
    },
}
<|endoftext|>


<commit_before>import NodePatcher from './NodePatcher';
import type { Node, ParseContext, Editor } from './types';

export default class BlockPatcher extends NodePatcher {
  constructor(node: Node, context: ParseContext, editor: Editor, statements: Array<NodePatcher>) {
    super(node, context, editor);
    this.statements = statements;
  }

  canPatchAsExpression(): boolean {
    return this.statements.every(
      statement => statement.prefersToPatchAsExpression()
    );
  }

  setExpression(force=false): boolean {
    let willPatchAsExpression = super.setExpression(force);
    if (willPatchAsExpression && this.prefersToPatchAsExpression()) {
      this.statements.forEach(statement => statement.setExpression());
    }
  }

  setImplicitlyReturns() {
    this.statements[this.statements.length - 1].setImplicitlyReturns();
  }

  patchAsStatement({ leftBrace=true, rightBrace=true }={}) {
    if (leftBrace) {
      this.insertBefore('{');
    }

    let { statements } = this;
    statements.forEach(
      statement => {
        if (statement.implicitlyReturns() && !statement.explicitlyReturns()) {
          this.insert(statement.before, 'return ');
        }
        statement.patch();
        // FIXME: Implicit returns may have different semicolon needs.
        if (statement.statementNeedsSemicolon() && this.shouldAppendSemicolonToStatement(statement)) {
          this.insert(statement.after, ';');
        }
      }
    );

    if (rightBrace) {
      if (this.inline()) {
        this.insertAfter(' }');
      } else {
        this.appendLineAfter('}', -1);
      }
    }
  }

  patchAsExpression({
    leftBrace=this.statements.length > 1,
    rightBrace=this.statements.length > 1
    }={}) {
    if (leftBrace) {
      this.insertBefore('(');
    }
    this.statements.forEach(
      (statement, i, statements) => {
        statement.patch();
        if (i !== statements.length - 1) {
          this.insert(statement.after, ', ');
        }
      }
    );
    if (rightBrace) {
      this.insertAfter(')');
    }
  }

  /**
   * @private
   */
  shouldAppendSemicolonToStatement(statement: NodePatcher): boolean {
    let { context } = this;
    let tokenAfterStatement = context.tokenAtIndex(statement.afterTokenIndex + 1);

    if (!tokenAfterStatement) {
      return true;
    }

    switch (tokenAfterStatement.type) {
      case 'TERMINATOR':
        break;

      case 'OUTDENT':
        // CoffeeScript does not insert a TERMINATOR before an OUTDENT.
        return true;

      default:
        if (this.inline()) {
          return true;
        } else {
          throw this.error(
            `unexpected non-terminator following ${statement.node.type} ` +
            `statement: ${tokenAfterStatement.type}`,
            tokenAfterStatement.range[0],
            tokenAfterStatement.range[1]
          );
        }
    }

    if (tokenAfterStatement.data === ';') {
      return false;
    }

    // CoffeeScript ignores ';' in ';\n', generating a token for '\n' instead,
    // so this terminator may actually be preceded by a semicolon. Let's just
    // look at characters following the end.
    let i = statement.after;
    for (;;) {
      switch (context.source.slice(i, i + 1)) {
        case ' ':
        case '\t':
          i++;
          break;

        case ';':
          return false;

        default:
          return true;
      }
    }
  }

  /**
   * Blocks never have semicolons after them.
   */
  statementNeedsSemicolon(): boolean {
    return false;
  }

  /**
   * Gets whether this patcher's block is inline (on the same line as the node
   * that contains it) or not.
   */
  inline(): boolean {
    return this.node.inline;
  }
}
<commit_msg>Do not add spaces between sequence expressions.<commit_after>import NodePatcher from './NodePatcher';
import type { Node, ParseContext, Editor } from './types';

export default class BlockPatcher extends NodePatcher {
  constructor(node: Node, context: ParseContext, editor: Editor, statements: Array<NodePatcher>) {
    super(node, context, editor);
    this.statements = statements;
  }

  canPatchAsExpression(): boolean {
    return this.statements.every(
      statement => statement.prefersToPatchAsExpression()
    );
  }

  setExpression(force=false): boolean {
    let willPatchAsExpression = super.setExpression(force);
    if (willPatchAsExpression && this.prefersToPatchAsExpression()) {
      this.statements.forEach(statement => statement.setExpression());
    }
  }

  setImplicitlyReturns() {
    this.statements[this.statements.length - 1].setImplicitlyReturns();
  }

  patchAsStatement({ leftBrace=true, rightBrace=true }={}) {
    if (leftBrace) {
      this.insertBefore('{');
    }

    let { statements } = this;
    statements.forEach(
      statement => {
        if (statement.implicitlyReturns() && !statement.explicitlyReturns()) {
          this.insert(statement.before, 'return ');
        }
        statement.patch();
        // FIXME: Implicit returns may have different semicolon needs.
        if (statement.statementNeedsSemicolon() && this.shouldAppendSemicolonToStatement(statement)) {
          this.insert(statement.after, ';');
        }
      }
    );

    if (rightBrace) {
      if (this.inline()) {
        this.insertAfter(' }');
      } else {
        this.appendLineAfter('}', -1);
      }
    }
  }

  patchAsExpression({
    leftBrace=this.statements.length > 1,
    rightBrace=this.statements.length > 1
    }={}) {
    if (leftBrace) {
      this.insertBefore('(');
    }
    this.statements.forEach(
      (statement, i, statements) => {
        statement.patch();
        if (i !== statements.length - 1) {
          this.insert(statement.after, ',');
        }
      }
    );
    if (rightBrace) {
      this.insertAfter(')');
    }
  }

  /**
   * @private
   */
  shouldAppendSemicolonToStatement(statement: NodePatcher): boolean {
    let { context } = this;
    let tokenAfterStatement = context.tokenAtIndex(statement.afterTokenIndex + 1);

    if (!tokenAfterStatement) {
      return true;
    }

    switch (tokenAfterStatement.type) {
      case 'TERMINATOR':
        break;

      case 'OUTDENT':
        // CoffeeScript does not insert a TERMINATOR before an OUTDENT.
        return true;

      default:
        if (this.inline()) {
          return true;
        } else {
          throw this.error(
            `unexpected non-terminator following ${statement.node.type} ` +
            `statement: ${tokenAfterStatement.type}`,
            tokenAfterStatement.range[0],
            tokenAfterStatement.range[1]
          );
        }
    }

    if (tokenAfterStatement.data === ';') {
      return false;
    }

    // CoffeeScript ignores ';' in ';\n', generating a token for '\n' instead,
    // so this terminator may actually be preceded by a semicolon. Let's just
    // look at characters following the end.
    let i = statement.after;
    for (;;) {
      switch (context.source.slice(i, i + 1)) {
        case ' ':
        case '\t':
          i++;
          break;

        case ';':
          return false;

        default:
          return true;
      }
    }
  }

  /**
   * Blocks never have semicolons after them.
   */
  statementNeedsSemicolon(): boolean {
    return false;
  }

  /**
   * Gets whether this patcher's block is inline (on the same line as the node
   * that contains it) or not.
   */
  inline(): boolean {
    return this.node.inline;
  }
}
<|endoftext|>


<commit_before>"use strict";

var xmltools = {

    isString : function (obj) {
        return (Object.prototype.toString.call(obj) === '[object String]');
    },

    checkString : function(d) {
        if (this.isString(d)) return d;
        else return "";
    },

    nodeAsArray : function (node) {
        let a = [];
        if (node) {
            //return, if already an array
            if (node instanceof Array) return node;

            //else push node into an array
            a.push(node);
        }
        return a;
    },

    getWbxmlDataField: function(wbxmlData,path) {
    if (wbxmlData) {
        let pathElements = path.split(".");
        let data = wbxmlData;
        let valid = true;
        for (let x = 0; valid && x < pathElements.length; x++) {
            if (data[pathElements[x]]) data = data[pathElements[x]];
            else valid = false;
        }
        if (valid) return data;
    }
    return false
    },

    //print content of xml data object (if debug output enabled)
    printXmlData : function (data, lvl = 0) {
        if ((tbSync.prefSettings.getBoolPref("log.toconsole") || tbSync.prefSettings.getBoolPref("log.tofile")) && tbSync.prefSettings.getBoolPref("log.easdata")) {
            let dump = "";
            for (let d in data) {
                if (typeof(data[d]) == "object") {
                    dump = dump + " ".repeat(lvl) + d + " => \n" + this.printXmlData(data[d], lvl+1);
                    dump = dump + " ".repeat(lvl) + d + " <= \n";
                } else {
                    dump = dump + " ".repeat(lvl) + d + " = [" + data[d] + "]\n";
                }
            }
            if (lvl == 0) tbSync.dump("Extracted XML data", "\n" + dump);
            else return dump;
        }
    },

    getDataFromXMLString: function (str) {
        let data = null;
        let xml = "";
        if (str == "") return data;

        let oParser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
        try {
            xml = oParser.parseFromString(str, "application/xml");
        } catch (e) {
            //however, domparser does not throw an error, it returns an error document
            //https://developer.mozilla.org/de/docs/Web/API/DOMParser
            //just in case
            throw eas.finishSync("mailformed-xml", eas.flags.abortWithError);
        }

        //check if xml is error document
        if (xml.documentElement.nodeName == "parsererror") {
            tbSync.dump("BAD XML",str);
            throw eas.finishSync("mailformed-xml", eas.flags.abortWithError);
        }

        try {
            data = this.getDataFromXML(xml);
        } catch (e) {
            throw eas.finishSync("mailformed-data", eas.flags.abortWithError);
        }

        return data;
    },

    //create data object from XML node
    getDataFromXML : function (nodes) {

        /*
         * The passed nodes value could be an entire document in a single node (type 9) or a
         * single element node (type 1) as returned by getElementById. It could however also
         * be an array of nodes as returned by getElementsByTagName or a nodeList as returned
         * by childNodes. In that case node.length is defined.
         */

        // create the return object
        let obj = {};
        let nodeList = [];
        let multiplicity = {};

        if (nodes.length === undefined) nodeList.push(nodes);
        else nodeList = nodes;

        // nodelist contains all childs, if two childs have the same name, we cannot add the chils as an object, but as an array of objects
        for (let node of nodeList) {
            if (node.nodeType == 1 || node.nodeType == 3) {
                if (!multiplicity.hasOwnProperty(node.nodeName)) multiplicity[node.nodeName] = 0;
                multiplicity[node.nodeName]++;
                //if this nodeName has multiplicity > 1, prepare obj  (but only once)
                if (multiplicity[node.nodeName]==2) obj[node.nodeName] = [];
            }
        }

        // process nodes
        for (let node of nodeList) {
            switch (node.nodeType) {
                case 9:
                    //document node, dive directly and process all children
                    if (node.hasChildNodes) obj = this.getDataFromXML(node.childNodes);
                    break;
                case 1:
                    //element node
                    if (node.hasChildNodes) {
                        //if this is an element with only one text child, do not dive, but get text childs value
                        let o;
                        if (node.childNodes.length == 1 && node.childNodes.item(0).nodeType==3) {
                            o = node.childNodes.item(0).nodeValue;
                        } else {
                            o = this.getDataFromXML(node.childNodes);
                        }
                        //check, if we can add the object directly, or if we have to push it into an array
                        if (multiplicity[node.nodeName]>1) obj[node.nodeName].push(o)
                        else obj[node.nodeName] = o;
                    }
                    break;
            }
        }
        return obj;
    }

};
<commit_msg>whitespaces<commit_after>"use strict";

var xmltools = {

    isString : function (obj) {
        return (Object.prototype.toString.call(obj) === '[object String]');
    },

    checkString : function(d) {
        if (this.isString(d)) return d;
        else return "";
    },

    nodeAsArray : function (node) {
        let a = [];
        if (node) {
            //return, if already an array
            if (node instanceof Array) return node;

            //else push node into an array
            a.push(node);
        }
        return a;
    },

    getWbxmlDataField: function(wbxmlData,path) {
        if (wbxmlData) {
            let pathElements = path.split(".");
            let data = wbxmlData;
            let valid = true;
            for (let x = 0; valid && x < pathElements.length; x++) {
                if (data[pathElements[x]]) data = data[pathElements[x]];
                else valid = false;
            }
            if (valid) return data;
        }
        return false
    },

    //print content of xml data object (if debug output enabled)
    printXmlData : function (data, lvl = 0) {
        if ((tbSync.prefSettings.getBoolPref("log.toconsole") || tbSync.prefSettings.getBoolPref("log.tofile")) && tbSync.prefSettings.getBoolPref("log.easdata")) {
            let dump = "";
            for (let d in data) {
                if (typeof(data[d]) == "object") {
                    dump = dump + " ".repeat(lvl) + d + " => \n" + this.printXmlData(data[d], lvl+1);
                    dump = dump + " ".repeat(lvl) + d + " <= \n";
                } else {
                    dump = dump + " ".repeat(lvl) + d + " = [" + data[d] + "]\n";
                }
            }
            if (lvl == 0) tbSync.dump("Extracted XML data", "\n" + dump);
            else return dump;
        }
    },

    getDataFromXMLString: function (str) {
        let data = null;
        let xml = "";
        if (str == "") return data;

        let oParser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
        try {
            xml = oParser.parseFromString(str, "application/xml");
        } catch (e) {
            //however, domparser does not throw an error, it returns an error document
            //https://developer.mozilla.org/de/docs/Web/API/DOMParser
            //just in case
            throw eas.finishSync("mailformed-xml", eas.flags.abortWithError);
        }

        //check if xml is error document
        if (xml.documentElement.nodeName == "parsererror") {
            tbSync.dump("BAD XML",str);
            throw eas.finishSync("mailformed-xml", eas.flags.abortWithError);
        }

        try {
            data = this.getDataFromXML(xml);
        } catch (e) {
            throw eas.finishSync("mailformed-data", eas.flags.abortWithError);
        }

        return data;
    },

    //create data object from XML node
    getDataFromXML : function (nodes) {

        /*
         * The passed nodes value could be an entire document in a single node (type 9) or a
         * single element node (type 1) as returned by getElementById. It could however also
         * be an array of nodes as returned by getElementsByTagName or a nodeList as returned
         * by childNodes. In that case node.length is defined.
         */

        // create the return object
        let obj = {};
        let nodeList = [];
        let multiplicity = {};

        if (nodes.length === undefined) nodeList.push(nodes);
        else nodeList = nodes;

        // nodelist contains all childs, if two childs have the same name, we cannot add the chils as an object, but as an array of objects
        for (let node of nodeList) {
            if (node.nodeType == 1 || node.nodeType == 3) {
                if (!multiplicity.hasOwnProperty(node.nodeName)) multiplicity[node.nodeName] = 0;
                multiplicity[node.nodeName]++;
                //if this nodeName has multiplicity > 1, prepare obj  (but only once)
                if (multiplicity[node.nodeName]==2) obj[node.nodeName] = [];
            }
        }

        // process nodes
        for (let node of nodeList) {
            switch (node.nodeType) {
                case 9:
                    //document node, dive directly and process all children
                    if (node.hasChildNodes) obj = this.getDataFromXML(node.childNodes);
                    break;
                case 1:
                    //element node
                    if (node.hasChildNodes) {
                        //if this is an element with only one text child, do not dive, but get text childs value
                        let o;
                        if (node.childNodes.length == 1 && node.childNodes.item(0).nodeType==3) {
                            o = node.childNodes.item(0).nodeValue;
                        } else {
                            o = this.getDataFromXML(node.childNodes);
                        }
                        //check, if we can add the object directly, or if we have to push it into an array
                        if (multiplicity[node.nodeName]>1) obj[node.nodeName].push(o)
                        else obj[node.nodeName] = o;
                    }
                    break;
            }
        }
        return obj;
    }

};
<|endoftext|>


<commit_before>(function(window, undefined){

	window.isInit = false;

	window.Asc.plugin.init = function(text)
	{
		if (!window.isInit)
		{
			window.isInit = true;

			window.Asc.plugin.currentText = "";
			window.Asc.plugin.createInputHelper();
			window.Asc.plugin.getInputHelper().createWindow();
		}
	};

	window.Asc.plugin.button = function(id)
	{
		this.executeCommand("close", "");
	};

	window.Asc.plugin.inputHelper_onSelectItem = function(item)
	{
		if (!item)
			return;

		window.Asc.plugin.executeMethod("InputText", [item.text]);
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperClear = function()
	{
		window.Asc.plugin.currentText = "";
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperInput = function(data)
	{
		if (data.add)
			window.Asc.plugin.currentText += data.text;
		else
			window.Asc.plugin.currentText = data.text;

		// correct by space
		var lastIndexSpace = window.Asc.plugin.currentText.lastIndexOf(" ");
		if (lastIndexSpace >= 0)
		{
			if (lastIndexSpace == (window.Asc.plugin.currentText.length - 1))
				window.Asc.plugin.currentText = "";
			else
				window.Asc.plugin.currentText = window.Asc.plugin.currentText.substr(lastIndexSpace + 1);
		}

		console.log("text: " + window.Asc.plugin.currentText);

		if (window.Asc.plugin.currentText.length < 3)
		{
			window.Asc.plugin.getInputHelper().unShow();
			return;
		}

		var variants = window.getAutoComplete(window.Asc.plugin.currentText);
		if (variants.length == 0)
		{
			window.Asc.plugin.getInputHelper().unShow();
		}
		else
		{
			var items = [];
			for (var i = 0; i < variants.length; i++)
			{
				items.push({ text : variants[i] });
			}

			window.Asc.plugin.getInputHelper().setItems(items);
			var _sizes = getInputHelperSize();
			window.Asc.plugin.getInputHelper().show(_sizes.w, _sizes.h, false);
		}
	};

	function getInputHelperSize()
	{
		var _size = window.Asc.plugin.getInputHelper().getScrollSizes();
		var _width = 200;// _size.w
		var _height = _size.h;
		var _heightMin = window.Asc.plugin.getInputHelper().getItemsHeight(Math.min(5, window.Asc.plugin.getInputHelper().getItems().length));

		if (_width > 400)
			_width = 400;
		if (_height > _heightMin)
			_height = _heightMin;

		_width += 30;

		return { w: _width, h : _height };
	}

	window.isAutoCompleteReady = false;
	window.getAutoComplete = function(text)
	{
		if (!g_dictionary)
			return;

		window.isAutoCompleteReady = true;
		g_dictionary.sort();

		var textFound = text.toLowerCase();

		var start = 0;
		var end = g_dictionary.length - 1;
		var index = 0;

		while (true)
		{
			var middle = (end + start) >> 1;

			if (middle == start || middle == end)
			{
				index = start;

				while (index != end)
				{
					if (g_dictionary[index] >= textFound)
						break;
					index++;
				}

				break;
			}

			var test = g_dictionary[middle];

			if (test == textFound)
			{
				index = middle;
				break;
			}

			if (test < textFound)
			{
				start = middle;
			}
			else
			{
				end = middle;
			}
		}

		var ret = [];
		end = g_dictionary.length;
		while (index < end)
		{
			var testRec = g_dictionary[index++];
			if (testRec.indexOf(textFound) != 0)
				break;

			ret.push(text + testRec.substr(textFound.length));
			index++;
		}

		return ret;
	};

})(window, undefined);
<commit_msg>Support Input helpers. developing...<commit_after>(function(window, undefined){

	window.isInit = false;

	window.Asc.plugin.init = function(text)
	{
		if (!window.isInit)
		{
			window.isInit = true;

			window.Asc.plugin.currentText = "";
			window.Asc.plugin.createInputHelper();
			window.Asc.plugin.getInputHelper().createWindow();
		}
	};

	window.Asc.plugin.button = function(id)
	{
		this.executeCommand("close", "");
	};

	window.Asc.plugin.inputHelper_onSelectItem = function(item)
	{
		if (!item)
			return;

		window.Asc.plugin.executeMethod("InputText", [item.text, window.Asc.plugin.currentText]);
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperClear = function()
	{
		window.Asc.plugin.currentText = "";
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperInput = function(data)
	{
		if (data.add)
			window.Asc.plugin.currentText += data.text;
		else
			window.Asc.plugin.currentText = data.text;

		// correct by space
		var lastIndexSpace = window.Asc.plugin.currentText.lastIndexOf(" ");
		if (lastIndexSpace >= 0)
		{
			if (lastIndexSpace == (window.Asc.plugin.currentText.length - 1))
				window.Asc.plugin.currentText = "";
			else
				window.Asc.plugin.currentText = window.Asc.plugin.currentText.substr(lastIndexSpace + 1);
		}

		if (window.Asc.plugin.currentText.length < 3)
		{
			window.Asc.plugin.getInputHelper().unShow();
			return;
		}

		var variants = window.getAutoComplete(window.Asc.plugin.currentText);
		if (variants.length == 0)
		{
			window.Asc.plugin.getInputHelper().unShow();
		}
		else
		{
			var items = [];
			for (var i = 0; i < variants.length; i++)
			{
				items.push({ text : variants[i] });
			}

			window.Asc.plugin.getInputHelper().setItems(items);
			var _sizes = getInputHelperSize();
			window.Asc.plugin.getInputHelper().show(_sizes.w, _sizes.h, false);
		}
	};

	function getInputHelperSize()
	{
		var _size = window.Asc.plugin.getInputHelper().getScrollSizes();
		var _width = 200;// _size.w
		var _height = _size.h;
		var _heightMin = window.Asc.plugin.getInputHelper().getItemsHeight(Math.min(5, window.Asc.plugin.getInputHelper().getItems().length));

		if (_width > 400)
			_width = 400;
		if (_height > _heightMin)
			_height = _heightMin;

		_width += 30;

		return { w: _width, h : _height };
	}

	window.isAutoCompleteReady = false;
	window.getAutoComplete = function(text)
	{
		if (!g_dictionary)
			return;

		window.isAutoCompleteReady = true;
		g_dictionary.sort();

		var textFound = text.toLowerCase();

		var start = 0;
		var end = g_dictionary.length - 1;
		var index = 0;

		while (true)
		{
			var middle = (end + start) >> 1;

			if (middle == start || middle == end)
			{
				index = start;

				while (index != end)
				{
					if (g_dictionary[index] >= textFound)
						break;
					index++;
				}

				break;
			}

			var test = g_dictionary[middle];

			if (test == textFound)
			{
				index = middle;
				break;
			}

			if (test < textFound)
			{
				start = middle;
			}
			else
			{
				end = middle;
			}
		}

		var ret = [];
		end = g_dictionary.length;
		while (index < end)
		{
			var testRec = g_dictionary[index++];
			if (testRec.indexOf(textFound) != 0)
				break;

			ret.push(text + testRec.substr(textFound.length));
			index++;
		}

		return ret;
	};

})(window, undefined);
<|endoftext|>