<commit_before>/**
 *	Bananatag Public API Node Library
 *
 * 	@author Bananatag Systems <eric@bananatag.com>
 * 	@version 1.0.0
 */

/*jshint onevar: false, indent:4 */
/*global setImmediate: false, setTimeout: false, console: false, process: true */
(function () {
    'use strict';
    var querystring = require('querystring'),
        Crypto = require('crypto'),
        Request = require('request'),
        async = require('async'),
        MailComposer = require('mailComposer').MailComposer,
        mailComposer = new MailComposer({'forceEmbeddedImages': true}),
        baseUrl;

    /**
     *	Unique API identifier
     */
    var authId;

    /**
     *	Unique API Access Key
     */
    var accessKey;

    /**
     * Constructor
     * @param: id
     * @param: key
     * @throws Exception
     */
    function BTagAPI(id, key) {
        if (Crypto === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'crypto' module.");
        }

        if (Request === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'makeRequest' module.");
        }

        if (async === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'Request' module.");
        }

        if (!id || !key) {
            throw new Error("401 (Unauthorized): You must provide both an authID and access key.");
        }

        authId = id;
        accessKey = key;
        baseUrl = "https://api.bananatag.com/";
    }

    var btRequest = {
        /**
         * Check data and setup makeRequest
         * @param endpoint
         * @param {object} params
         * @param {function} callback
         */
        send: function (endpoint, params, callback) {
            var self = btRequest;

            async.series(
                {
                    'check': function (next) {
                        self.checkData(params, next);
                    },
                    'method': function (next) {
                        self.getMethod(endpoint, next);
                    },
                    'signature': function (next) {
                        self.generateSignature(params, next)
                    }
                },
                function (err, req) {
                    if (err) {
                        callback(err);
                    }

                    self.makeRequest(baseUrl + endpoint, req, params, callback);
                }
            );
        },

        /**
         * Send GET/PUT makeRequest, parse json response and call callback with returned data
         * @param url
         * @param params
         * @param {function} callback
         * @throws Exception
         * @param req
         */
        makeRequest: function (url, req, params, callback) {
            try {
                Request({
                    url: url,
                    method: req.method,
                    form: params,
                    timeout: 10000,
                    headers: {
                        Authorization: req.signature
                    }
                }, function (err, response, body) {
                    if (err) {
                        callback(err);
                        return;
                    }

                    if (Math.floor(body.code / 100) >= 4) {
                        callback((body.code + " (" + body.error + "): " + body.message));
                    } else {
                        callback(null, body);
                    }
                });
            } catch (err) {
                 callback(null, err);
            }
        },

        /**
         * Check data and setup makeRequest
         * @param params
         * @param next
         */
        generateSignature: function (params, next) {
            try {
                var signature = Crypto.createHmac('sha1', accessKey).update(querystring.stringify(params)).digest('hex'),
                    rtn =  new Buffer(authId + ':' + signature).toString('base64');

                process.nextTick(function () {
                    next(null, rtn);
                });
            } catch (err) {
                process.nextTick(function () {
                    next(err, null);
                });
            }
        },

        /**
         * Return the correct makeRequest type for the given endpoint
         * @param endpoint
         * @param callback
         */
        getMethod: function (endpoint, callback) {
            setImmediate(function () {
                switch (endpoint) {
                    case "tags/send":
                        callback(null, 'POST');
                        break;
                    default:
                        callback(null, 'GET');
                }
            });
        },

        /**
         * Check data and catch any parameter errors before sending makeRequest
         * @param {object} data
         * @param {string} data.start
         * @param {string} data.end
         * @param callback
         */
        checkData: function (data, callback) {
            async.series([
                // Check date strings are in correct format
                function (next) {
                    if (data.start !== undefined) {
                        helpers.validateDate(data.start, next);
                    } else {
                        next(null);
                    }
                },
                // Check date strings are in correct format
                function (next) {
                    if (data.end !== undefined) {
                        helpers.validateDate(data.end, next);
                    } else {
                        next(null);
                    }
                },
                // Check if start date is less than end date.
                function (next) {
                    if (data.start !== undefined && data.end !== undefined) {
                        if ((Date.parse(data.start) / 1000) > (Date.parse(data.end) / 1000)) {
                            next("400 (Bad request): Error with provided parameters; Start date is greater than end date.");
                            return;
                        }
                    }

                    next(null);
                }
            ], function (err) {
                callback(err);
            });
        }
    };

    var btMime = {
        buildMessage: function (params, callback) {
            var that = this;
            var data = {};

            if (params.from === undefined) {
                callback("You must specify the from parameter.");
                return;
            } else if (params.to === undefined) {
                callback("You must include the to parameter.");
                return;
            } else if (params.html === undefined) {
                callback("You must include the html parameter.");
                return;
            } else if (params.text === undefined) {
                // TODO: make sure it is plaintext
                data.body = params.text;
            }

            // TODO: only allow 1 recipient or no limit?
            if (params.to.split(",") > 1) {
                throw new Error("You can only specify one to address.");
            }

            if (params.attachments !== undefined) {
                if (params.attachments.constructor !== Array) {
                    throw new Error("Attachments must be an array.");
                }
            }

            data.from = params.from;
            data.to = params.to;
            data.html = params.html;

            if (params.subject) {
                data.subject = params.subject;
            }

            if (params.cc) {
                data.cc = params.cc;
            }

            if (params.bcc) {
                data.bcc = params.bcc;
            }

            if (params.replyTo) {
                data.replyTo = params.replyTo;
            }

            if (params.inReplyTo) {
                data.inReplyTo = params.inReplyTo;
            }

            // Setup message data
            process.nextTick(function () {
                async.series([
                    // set basic email headers
                    function (next) {
                        mailComposer.setMessageOption(data);
                        next();
                    },
                    // add attachments if any are provided
                    function (next) {
                        if (params.attachments !== undefined && params.attachments.length > 0) {
                            that.addAttachments(mailComposer, params.attachments, function (err) {
                                (err) ? next(err) : next();
                            });
                        } else {
                            next();
                        }
                    }
                ], function (err) {
                    if (err) {
                        callback(err)
                        return;
                    }

                    // build the message into a mime message raw string
                    mailComposer.buildMessage(function(err, messageSource) {
                        if (err) {
                            callback(err);
                        } else {
                            // return Mime message as base64 encoded string
                            callback(null, new Buffer(messageSource).toString('base64'));
                        }
                    });
                });
            });
        },

        addAttachments: function (mailComposer, attachments, callback) {
            var data = {};
            async.each(attachments, function (attachment, next) {
                data = {};

                if (attachment.fileName === undefined) {
                    next("You must include the fileName parameter.");
                } else if (attachment.contents === undefined && attachment.filePath === undefined) {
                    next("You must include either the contents or filePath parameter.");
                }

                data.fileName = attachment.fileName;

                if (attachment.contents !== undefined) {
                    data.contents = attachment.contents;
                }

                if (attachment.filePath !== undefined) {
                    data.filePath = attachment.filePath;
                }

                if (attachment.streamSource !== undefined) {
                    data.streamSource = attachment.streamSource;
                }

                if (attachment.contentType !== undefined) {
                    data.contentType = attachment.contentType;
                }

                if (attachment.contentDisposition !== undefined ) {
                    data.contentDisposition = attachment.contentDisposition;
                }

                if (attachment.userAgent !== undefined) {
                    data.userAgent = attachment.userAgent;
                }

                mailComposer.addAttachment(data);

                process.nextTick(next)
            }, function (err) {
                callback(err);
            });
        }
    };

    var helpers = {
        /**
         * Check if date parameter is given in the correct format (yyyy-mm-dd)
         * @param date
         * @throws Exception
         * @param next
         */
            // TODO: only allow yyyy-mm-dd
        validateDate: function (date, next) {
            if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
                next(null);
            } else {
                next("400 (Bad request): Error with provided parameters; Date string must be in format yyyy-mm-dd.");
            }
        }
    };

    BTagAPI.prototype.request = btRequest.send;
    BTagAPI.prototype.getRaw = btMime.buildMessage;

    module.exports = BTagAPI;

}());<commit_msg>changing date validation to only allow yyyy-mm-dd<commit_after>/**
 *	Bananatag Public API Node Library
 *
 * 	@author Bananatag Systems <eric@bananatag.com>
 * 	@version 1.0.0
 */

/*jshint onevar: false, indent:4 */
/*global setImmediate: false, setTimeout: false, console: false, process: true */
(function () {
    'use strict';
    var querystring = require('querystring'),
        Crypto = require('crypto'),
        Request = require('request'),
        async = require('async'),
        MailComposer = require('mailComposer').MailComposer,
        mailComposer = new MailComposer({'forceEmbeddedImages': true}),
        baseUrl;

    /**
     *	Unique API identifier
     */
    var authId;

    /**
     *	Unique API Access Key
     */
    var accessKey;

    /**
     * Constructor
     * @param: id
     * @param: key
     * @throws Exception
     */
    function BTagAPI(id, key) {
        if (Crypto === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'crypto' module.");
        }

        if (Request === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'makeRequest' module.");
        }

        if (async === undefined) {
            throw new Error("400 (Bad request): The Bananatag-JS API library requires the 'Request' module.");
        }

        if (!id || !key) {
            throw new Error("401 (Unauthorized): You must provide both an authID and access key.");
        }

        authId = id;
        accessKey = key;
        baseUrl = "https://api.bananatag.com/";
    }

    var btRequest = {
        /**
         * Check data and setup makeRequest
         * @param endpoint
         * @param {object} params
         * @param {function} callback
         */
        send: function (endpoint, params, callback) {
            var self = btRequest;

            async.series(
                {
                    'check': function (next) {
                        self.checkData(params, next);
                    },
                    'method': function (next) {
                        self.getMethod(endpoint, next);
                    },
                    'signature': function (next) {
                        self.generateSignature(params, next)
                    }
                },
                function (err, req) {
                    if (err) {
                        callback(err);
                    }

                    self.makeRequest(baseUrl + endpoint, req, params, callback);
                }
            );
        },

        /**
         * Send GET/PUT makeRequest, parse json response and call callback with returned data
         * @param url
         * @param params
         * @param {function} callback
         * @throws Exception
         * @param req
         */
        makeRequest: function (url, req, params, callback) {
            try {
                Request({
                    url: url,
                    method: req.method,
                    form: params,
                    timeout: 10000,
                    headers: {
                        Authorization: req.signature
                    }
                }, function (err, response, body) {
                    if (err) {
                        callback(err);
                        return;
                    }

                    if (Math.floor(body.code / 100) >= 4) {
                        callback((body.code + " (" + body.error + "): " + body.message));
                    } else {
                        callback(null, body);
                    }
                });
            } catch (err) {
                 callback(null, err);
            }
        },

        /**
         * Check data and setup makeRequest
         * @param params
         * @param next
         */
        generateSignature: function (params, next) {
            try {
                var signature = Crypto.createHmac('sha1', accessKey).update(querystring.stringify(params)).digest('hex'),
                    rtn =  new Buffer(authId + ':' + signature).toString('base64');

                process.nextTick(function () {
                    next(null, rtn);
                });
            } catch (err) {
                process.nextTick(function () {
                    next(err, null);
                });
            }
        },

        /**
         * Return the correct makeRequest type for the given endpoint
         * @param endpoint
         * @param callback
         */
        getMethod: function (endpoint, callback) {
            setImmediate(function () {
                switch (endpoint) {
                    case "tags/send":
                        callback(null, 'POST');
                        break;
                    default:
                        callback(null, 'GET');
                }
            });
        },

        /**
         * Check data and catch any parameter errors before sending makeRequest
         * @param {object} data
         * @param {string} data.start
         * @param {string} data.end
         * @param callback
         */
        checkData: function (data, callback) {
            async.series([
                // Check date strings are in correct format
                function (next) {
                    if (data.start !== undefined) {
                        helpers.validateDate(data.start, next);
                    } else {
                        next(null);
                    }
                },
                // Check date strings are in correct format
                function (next) {
                    if (data.end !== undefined) {
                        helpers.validateDate(data.end, next);
                    } else {
                        next(null);
                    }
                },
                // Check if start date is less than end date.
                function (next) {
                    if (data.start !== undefined && data.end !== undefined) {
                        if ((Date.parse(data.start) / 1000) > (Date.parse(data.end) / 1000)) {
                            next("400 (Bad request): Error with provided parameters; Start date is greater than end date.");
                            return;
                        }
                    }

                    next(null);
                }
            ], function (err) {
                callback(err);
            });
        }
    };

    var btMime = {
        buildMessage: function (params, callback) {
            var that = this;
            var data = {};

            if (params.from === undefined) {
                callback("You must specify the from parameter.");
                return;
            } else if (params.to === undefined) {
                callback("You must include the to parameter.");
                return;
            } else if (params.html === undefined) {
                callback("You must include the html parameter.");
                return;
            } else if (params.text === undefined) {
                // TODO: make sure it is plaintext
                data.body = params.text;
            }

            // TODO: only allow 1 recipient or no limit?
            if (params.to.split(",") > 1) {
                throw new Error("You can only specify one to address.");
            }

            if (params.attachments !== undefined) {
                if (params.attachments.constructor !== Array) {
                    throw new Error("Attachments must be an array.");
                }
            }

            data.from = params.from;
            data.to = params.to;
            data.html = params.html;

            if (params.subject) {
                data.subject = params.subject;
            }

            if (params.cc) {
                data.cc = params.cc;
            }

            if (params.bcc) {
                data.bcc = params.bcc;
            }

            if (params.replyTo) {
                data.replyTo = params.replyTo;
            }

            if (params.inReplyTo) {
                data.inReplyTo = params.inReplyTo;
            }

            // Setup message data
            process.nextTick(function () {
                async.series([
                    // set basic email headers
                    function (next) {
                        mailComposer.setMessageOption(data);
                        next();
                    },
                    // add attachments if any are provided
                    function (next) {
                        if (params.attachments !== undefined && params.attachments.length > 0) {
                            that.addAttachments(mailComposer, params.attachments, function (err) {
                                (err) ? next(err) : next();
                            });
                        } else {
                            next();
                        }
                    }
                ], function (err) {
                    if (err) {
                        callback(err)
                        return;
                    }

                    // build the message into a mime message raw string
                    mailComposer.buildMessage(function(err, messageSource) {
                        if (err) {
                            callback(err);
                        } else {
                            // return Mime message as base64 encoded string
                            callback(null, new Buffer(messageSource).toString('base64'));
                        }
                    });
                });
            });
        },

        addAttachments: function (mailComposer, attachments, callback) {
            var data = {};
            async.each(attachments, function (attachment, next) {
                data = {};

                if (attachment.fileName === undefined) {
                    next("You must include the fileName parameter.");
                } else if (attachment.contents === undefined && attachment.filePath === undefined) {
                    next("You must include either the contents or filePath parameter.");
                }

                data.fileName = attachment.fileName;

                if (attachment.contents !== undefined) {
                    data.contents = attachment.contents;
                }

                if (attachment.filePath !== undefined) {
                    data.filePath = attachment.filePath;
                }

                if (attachment.streamSource !== undefined) {
                    data.streamSource = attachment.streamSource;
                }

                if (attachment.contentType !== undefined) {
                    data.contentType = attachment.contentType;
                }

                if (attachment.contentDisposition !== undefined ) {
                    data.contentDisposition = attachment.contentDisposition;
                }

                if (attachment.userAgent !== undefined) {
                    data.userAgent = attachment.userAgent;
                }

                mailComposer.addAttachment(data);

                process.nextTick(next)
            }, function (err) {
                callback(err);
            });
        }
    };

    var helpers = {
        /**
         * Check if date parameter is given in the correct format (yyyy-mm-dd)
         * @param date
         * @throws Exception
         * @param next
         */
        validateDate: function (date, next) {
            if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
                next(null);
            } else {
                next("400 (Bad request): Error with provided parameters; Date string must be in format yyyy-mm-dd.");
            }
        }
    };

    BTagAPI.prototype.request = btRequest.send;
    BTagAPI.prototype.getRaw = btMime.buildMessage;

    module.exports = BTagAPI;

}());<|endoftext|>


<commit_before>#! /usr/bin/env node

/*
 * calc
 * https://github.com/jonathan-fielding/CalcCLI
 *
 * Copyright (c) 2013 Jonathan Fielding
 * Licensed under the MIT license.
 */

'use strict';

var program = require('commander');
var _ = require('underscore');
var answer = null;

program
  .version('0.1.0')
  .option('--number1 <int>', 'specify the first number to add together',Number)
  .option('--number2 <int>', 'specify the second number to add together',Number)
  .parse(process.argv);

if(_.isUndefined(program.number1) || _.isUndefined(program.number2)){
	console.log('Please check your arguments, check --help for details')
}
else{
	if(_.isNaN(program.number1) || _.isNaN(program.number2)){
		console.log('Please only enter numbers');
	}
	else{
		answer = program.number1 + program.number2;
		console.log(answer);
	}
}

<commit_msg>missing ; added<commit_after>#! /usr/bin/env node

/*
 * calc
 * https://github.com/jonathan-fielding/CalcCLI
 *
 * Copyright (c) 2013 Jonathan Fielding
 * Licensed under the MIT license.
 */

'use strict';

var program = require('commander');
var _ = require('underscore');
var answer = null;

program
  .version('0.1.0')
  .option('--number1 <int>', 'specify the first number to add together',Number)
  .option('--number2 <int>', 'specify the second number to add together',Number)
  .parse(process.argv);

if(_.isUndefined(program.number1) || _.isUndefined(program.number2)){
	console.log('Please check your arguments, check --help for details');
}
else{
	if(_.isNaN(program.number1) || _.isNaN(program.number2)){
		console.log('Please only enter numbers');
	}
	else{
		answer = program.number1 + program.number2;
		console.log(answer);
	}
}

<|endoftext|>


<commit_before>import { color, default as echarts } from './echarts-base'
import { getType } from './util'

export default {
  props: {
    data: { type: [Object, Array], default () { return {} } },
    settings: { type: Object, default () { return {} } },
    width: { type: String, default: 'auto' },
    height: { type: String, default: '400px' },
    beforeConfig: { type: Function },
    afterConfig: { type: Function },
    afterSetOption: { type: Function },
    afterSetOptionOnce: { type: Function },
    events: { type: Object },
    grid: { type: Object },
    colors: { type: Array },
    tooltipVisible: { type: Boolean, default: true },
    legendVisible: { type: Boolean, default: true },
    legendPosition: { type: String },
    markLine: { type: Object },
    markArea: { type: Object },
    markPoint: { type: Object },
    visualMap: { type: [Object, Array] },
    dataZoom: { type: [Object, Array] },
    toolbox: { type: Object },
    initOptions: { type: Object, default () { return {} } },
    title: Object,
    legend: Object,
    xAxis: Object,
    yAxis: Object,
    radar: Object,
    tooltip: Object,
    axisPointer: Object,
    brush: Object,
    geo: Object,
    timeline: Object,
    graphic: Object,
    series: [Object, Array],
    backgroundColor: [Object, String],
    textStyle: Object,
    animation: Object,
    theme: Object,
    themeName: String
  },

  watch: {
    data: {
      deep: true,
      handler (v) {
        if (v) { this.dataHandler(v) }
      }
    },

    settings: {
      deep: true,
      handler (v) {
        if (v.type && this.chartLib) this.chartHandler = this.chartLib[v.type]
        this.dataHandler(this.data)
      }
    }
  },

  computed: {
    canvasStyle () {
      return {
        width: this.width,
        height: this.height,
        position: 'relative'
      }
    },

    chartColor () {
      return this.colors || (this.theme && this.theme.color) || color
    }
  },

  methods: {
    dataHandler (data) {
      if (!this.chartHandler) return
      const { columns = [], rows = [] } = data
      const extra = {
        tooltipVisible: this.tooltipVisible,
        legendVisible: this.legendVisible,
        echarts: this.echarts,
        color: this.chartColor
      }
      if (this.beforeConfig) data = this.beforeConfig(data)

      let options = this.chartHandler(columns, rows, this.settings, extra)
      if (options) {
        if (typeof options.then === 'function') {
          options.then(this.optionsHandler)
        } else {
          this.optionsHandler(options)
        }
      }
    },

    optionsHandler (options) {
      if (this.legendPosition && options.legend) {
        options.legend[this.legendPosition] = 10
        if (~['left', 'right'].indexOf(this.legendPosition)) {
          options.legend.top = 'middle'
          options.legend.orient = 'vertical'
        }
      }
      if (!this.themeName) options.color = this.chartColor
      const echartsSettings = [
        'grid', 'dataZoom', 'visualMap', 'toolbox', 'title', 'legend',
        'xAxis', 'yAxis', 'radar', 'tooltip', 'axisPointer', 'brush',
        'geo', 'timeline', 'graphic', 'series', 'backgroundColor',
        'textStyle'
      ]
      echartsSettings.forEach(setting => {
        if (this[setting]) options[setting] = this[setting]
      })
      if (this.animation) {
        Object.keys(this.animation).forEach(key => {
          options[key] = this.animation[key]
        })
      }
      if (this.markArea || this.markLine || this.markPoint) {
        const marks = {
          markArea: this.markArea,
          markLine: this.markLine,
          markPoint: this.markPoint
        }
        const series = options.series
        if (getType(series) === '[object Array]') {
          series.forEach(item => {
            this.addMark(item, marks)
          })
        } else if (getType(series) === '[object Object]') {
          this.addMark(series, marks)
        }
      }
      if (this.afterConfig) options = this.afterConfig(options)
      this.echarts.setOption(options, true)
      if (this.afterSetOption) this.afterSetOption(this.echarts)
      if (this.afterSetOptionOnce && !this._once['afterSetOptionOnce']) {
        this._once['afterSetOptionOnce'] = this.afterSetOptionOnce(this.echarts)
      }
    },

    addMark (seriesItem, marks) {
      Object.keys(marks).forEach(key => {
        if (marks[key]) {
          seriesItem[key] = marks[key]
        }
      })
    },

    init () {
      if (this.echarts) return
      const themeName = this.themeName || (this.theme ? 'outer-theme' : 've-chart')
      this.echarts = this.echartsLib.init(this.$refs.canvas, themeName, this.initOptions)
      if (this.data) this.dataHandler(this.data)
      if (this.events) this.bindEvents()
    },

    bindEvents () {
      Object.keys(this.events).forEach(event => {
        this.echarts.on(event, this.events[event])
      })
    },

    addWatchToProps () {
      const watchedVariable = this._watchers.map(watcher => watcher.expression)
      Object.keys(this.$props).forEach(prop => {
        if (!~watchedVariable.indexOf(prop)) {
          const opts = {}
          if (getType(prop) === '[object Object]') {
            opts.deep = true
          }
          this.$watch(prop, () => {
            this.dataHandler(this.data)
          }, opts)
        }
      })
    },

    registerTheme () {
      echarts.registerTheme('outer-theme', this.theme)
    }
  },

  created () {
    this.echarts = null
    this._once = {}
    this.addWatchToProps()
    if (this.theme) this.registerTheme()
  },

  mounted () {
    this.init()
    window.addEventListener('resize', this.echarts.resize)
  },

  beforeDestory () {
    window.removeEventListener('resize', this.echarts.resize)
    this.echarts.dispose()
  }
}
<commit_msg>修复：typo<commit_after>import { color, default as echarts } from './echarts-base'
import { getType } from './util'

export default {
  props: {
    data: { type: [Object, Array], default () { return {} } },
    settings: { type: Object, default () { return {} } },
    width: { type: String, default: 'auto' },
    height: { type: String, default: '400px' },
    beforeConfig: { type: Function },
    afterConfig: { type: Function },
    afterSetOption: { type: Function },
    afterSetOptionOnce: { type: Function },
    events: { type: Object },
    grid: { type: Object },
    colors: { type: Array },
    tooltipVisible: { type: Boolean, default: true },
    legendVisible: { type: Boolean, default: true },
    legendPosition: { type: String },
    markLine: { type: Object },
    markArea: { type: Object },
    markPoint: { type: Object },
    visualMap: { type: [Object, Array] },
    dataZoom: { type: [Object, Array] },
    toolbox: { type: Object },
    initOptions: { type: Object, default () { return {} } },
    title: Object,
    legend: Object,
    xAxis: Object,
    yAxis: Object,
    radar: Object,
    tooltip: Object,
    axisPointer: Object,
    brush: Object,
    geo: Object,
    timeline: Object,
    graphic: Object,
    series: [Object, Array],
    backgroundColor: [Object, String],
    textStyle: Object,
    animation: Object,
    theme: Object,
    themeName: String
  },

  watch: {
    data: {
      deep: true,
      handler (v) {
        if (v) { this.dataHandler(v) }
      }
    },

    settings: {
      deep: true,
      handler (v) {
        if (v.type && this.chartLib) this.chartHandler = this.chartLib[v.type]
        this.dataHandler(this.data)
      }
    }
  },

  computed: {
    canvasStyle () {
      return {
        width: this.width,
        height: this.height,
        position: 'relative'
      }
    },

    chartColor () {
      return this.colors || (this.theme && this.theme.color) || color
    }
  },

  methods: {
    dataHandler (data) {
      if (!this.chartHandler) return
      const { columns = [], rows = [] } = data
      const extra = {
        tooltipVisible: this.tooltipVisible,
        legendVisible: this.legendVisible,
        echarts: this.echarts,
        color: this.chartColor
      }
      if (this.beforeConfig) data = this.beforeConfig(data)

      let options = this.chartHandler(columns, rows, this.settings, extra)
      if (options) {
        if (typeof options.then === 'function') {
          options.then(this.optionsHandler)
        } else {
          this.optionsHandler(options)
        }
      }
    },

    optionsHandler (options) {
      if (this.legendPosition && options.legend) {
        options.legend[this.legendPosition] = 10
        if (~['left', 'right'].indexOf(this.legendPosition)) {
          options.legend.top = 'middle'
          options.legend.orient = 'vertical'
        }
      }
      if (!this.themeName) options.color = this.chartColor
      const echartsSettings = [
        'grid', 'dataZoom', 'visualMap', 'toolbox', 'title', 'legend',
        'xAxis', 'yAxis', 'radar', 'tooltip', 'axisPointer', 'brush',
        'geo', 'timeline', 'graphic', 'series', 'backgroundColor',
        'textStyle'
      ]
      echartsSettings.forEach(setting => {
        if (this[setting]) options[setting] = this[setting]
      })
      if (this.animation) {
        Object.keys(this.animation).forEach(key => {
          options[key] = this.animation[key]
        })
      }
      if (this.markArea || this.markLine || this.markPoint) {
        const marks = {
          markArea: this.markArea,
          markLine: this.markLine,
          markPoint: this.markPoint
        }
        const series = options.series
        if (getType(series) === '[object Array]') {
          series.forEach(item => {
            this.addMark(item, marks)
          })
        } else if (getType(series) === '[object Object]') {
          this.addMark(series, marks)
        }
      }
      if (this.afterConfig) options = this.afterConfig(options)
      this.echarts.setOption(options, true)
      if (this.afterSetOption) this.afterSetOption(this.echarts)
      if (this.afterSetOptionOnce && !this._once['afterSetOptionOnce']) {
        this._once['afterSetOptionOnce'] = this.afterSetOptionOnce(this.echarts)
      }
    },

    addMark (seriesItem, marks) {
      Object.keys(marks).forEach(key => {
        if (marks[key]) {
          seriesItem[key] = marks[key]
        }
      })
    },

    init () {
      if (this.echarts) return
      const themeName = this.themeName || (this.theme ? 'outer-theme' : 've-chart')
      this.echarts = this.echartsLib.init(this.$refs.canvas, themeName, this.initOptions)
      if (this.data) this.dataHandler(this.data)
      if (this.events) this.bindEvents()
    },

    bindEvents () {
      Object.keys(this.events).forEach(event => {
        this.echarts.on(event, this.events[event])
      })
    },

    addWatchToProps () {
      const watchedVariable = this._watchers.map(watcher => watcher.expression)
      Object.keys(this.$props).forEach(prop => {
        if (!~watchedVariable.indexOf(prop)) {
          const opts = {}
          if (getType(prop) === '[object Object]') {
            opts.deep = true
          }
          this.$watch(prop, () => {
            this.dataHandler(this.data)
          }, opts)
        }
      })
    },

    registerTheme () {
      echarts.registerTheme('outer-theme', this.theme)
    }
  },

  created () {
    this.echarts = null
    this._once = {}
    this.addWatchToProps()
    if (this.theme) this.registerTheme()
  },

  mounted () {
    this.init()
    window.addEventListener('resize', this.echarts.resize)
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.echarts.resize)
    this.echarts.dispose()
  }
}
<|endoftext|>


<commit_before>if(!window.console) console = {log: function() {}};
<commit_msg>Handle login required headers on the client side.<commit_after>if(!window.console) console = {log: function() {}};

$(function(){
    $('body').ajaxComplete(function(event, XmlHttpRequest, ajaxOptions){
        if (XmlHttpRequest.getResponseHeader('X-Django-Requires-Auth')) {
            var next = window.location.pathname + window.location.hash;
            window.location = XmlHttpRequest.getResponseHeader('X-Django-Login-Url') + '?next=' + next;
        }
    });
});
<|endoftext|>


<commit_before>"use strict";
VDom.UI = {
  box: null,
  styleIn: null,
  styleOut: null,
  root: null,
  focusedEl: null,
  flashLastingTime: 400,
  showing: true,
  addElement: function(element, showOnInit) {
    this.showing = showOnInit !== false;
    VPort.send({ handler: "initInnerCSS" }, this.InitInner);
    this.init && this.init(false);
    this.box.style.display = "none";
    this.root = this.box.createShadowRoot();
    this.root.appendChild(element);
    this.addElement = function(element) {
      this.root.appendChild(element);
      this.adjust();
    };
  },
  addElementList: function(els, id, offset) {
    var parent, _i, _len, style;
    parent = VDom.createElement("div");
    parent.className = "R LS";
    parent.id = id;
    for (_i = 0, _len = els.length; _i < _len; _i++) {
      parent.appendChild(els[_i]);
    }
    style = parent.style;
    style.left = offset[0] + "px"; style.top = offset[1] + "px";
    (_i = VDom.bodyZoom) !== 1 && (style.zoom = _i);
    document.webkitIsFullScreen && (style.position = "fixed");
    this.addElement(parent);
    return parent;
  },
  adjust: function() {
    (!this.InitInner && document.webkitFullscreenElement || document.documentElement).appendChild(this.box);
  },
  init: function(showing) {
    this.box = VDom.createElement("vimium");
    showing !== false && this.adjust();
    this.init = null;
  },
  InitInner: function(innerCSS) {
    var _this = VDom.UI;
    _this.InitInner = null;
    _this.styleIn = _this.createStyle(innerCSS);
    _this.root.insertBefore(_this.styleIn, _this.root.firstElementChild);
    _this.showing && setTimeout(function() {
      _this.box.style.display = "";
      var el = _this.focusedEl; _this.focusedEl = null;
      el && setTimeout(function() { el.focus(); }, 17);
    }, 17);
    _this.adjust();
  },
  toggle: function(enabled) {
    if (!enabled) { this.box.remove(); return; }
    this.box.parentNode || this.adjust();
  },
  createStyle: function(text, doc) {
    var css = (doc || VDom).createElement("style");
    css.type = "text/css";
    css.textContent = text;
    return css;
  },
  InsertInnerCSS: function(inner) {
    VDom.UI.styleIn && (VDom.UI.styleIn.textContent = inner.css);
  },
  insertCSS: function(outer) {
    var el = this.styleOut;
    if (!outer) { el && el.remove(); return; }
    el ? (el.textContent = outer) : (el = this.styleOut = this.createStyle(outer));
    this.init && this.init();
    this.box.appendChild(el);
  },
  getSelection: function() {
    var sel = window.getSelection(), el, el2;
    if (sel.focusNode === document.documentElement && (el = VScroller.current)) {
      for (; el2 = el.parentNode; el = el2) {}
      if (el.getSelection) { sel = el.getSelection() || sel; }
    }
    return sel;
  },
  removeSelection: function(root) {
    var sel = (root || this.root).getSelection();
    if (sel.type !== "Range" || !sel.anchorNode) {
      return false;
    }
    sel.removeAllRanges();
    return true;
  },
  simulateSelect: function(element, flash, suppressRepeated) {
    element.focus();
    VDom.simulateClick(element);
    flash === true && this.flash(element);
    if (element !== VEventMode.lock()) { return; }
    var len;
    if ((len = element.value ? element.value.length : -1) && element.setSelectionRange) {
      if (element instanceof HTMLInputElement || element.clientHeight + 12 >= element.scrollHeight)
      try {
        if (0 == element.selectionEnd) {
          element.setSelectionRange(len, len);
        }
      } catch (e) {}
    }
    suppressRepeated === true && this.suppressTail(true);
  },
  focus: function(el) {
    if (this.box.style.display) {
      this.focusedEl = el;
    } else {
      el.focus();
    }
  },
  getVRect: function(clickEl) {
    var rect, bcr, b = document.body;
    VDom.prepareCrop();
    VDom.bodyZoom = b && VDom.isInDOM(clickEl, b) && +getComputedStyle(b).zoom || 1;
    rect = VDom.getVisibleClientRect(clickEl);
    bcr = VRect.fromClientRect(clickEl.getBoundingClientRect());
    return rect && !VRect.isContaining(bcr, rect) ? rect
      : VDom.isVisibile(clickEl) ? bcr : null;
  },
  flash: function(el, rect) {
    rect || (rect = this.getVRect(el));
    if (!rect) { return; }
    var flashEl = VDom.createElement("div"), nfs = !document.webkitIsFullScreen;
    flashEl.className = "R Flash";
    VRect.setBoundary(flashEl.style, rect, nfs);
    VDom.bodyZoom !== 1 && nfs && (flashEl.style.zoom = VDom.bodyZoom);
    this.addElement(flashEl);
    return setTimeout(function() {
      flashEl.remove();
    }, this.flashLastingTime);
  },
  suppressTail: function(onlyRepeated) {
    var func, tick, timer;
    if (onlyRepeated) {
      func = function(event) {
        if (event.repeat) { return 2; }
        VHandler.remove(this);
        return 0;
      };
    } else {
      func = function() { tick = Date.now(); return 2; };
      tick = Date.now() + VSettings.cache.keyboard[0];
      timer = setInterval(function() {
        if (Date.now() - tick > 150) {
          clearInterval(timer);
          VHandler && VHandler.remove(func);
        }
      }, 75);
    }
    VHandler.push(func, func);
  },
  SuppressMost: function(event) {
    var key = event.keyCode;
    if (VKeyboard.isEscape(event)) {
      VHandler.remove(this);
    }
    return key > VKeyCodes.f1 + 9 && key <= VKeyCodes.f12 ? 1 : 2;
  }
};
<commit_msg>safer VDom.UI.adjust just for tests<commit_after>"use strict";
VDom.UI = {
  box: null,
  styleIn: null,
  styleOut: null,
  root: null,
  focusedEl: null,
  flashLastingTime: 400,
  showing: true,
  addElement: function(element, showOnInit) {
    this.showing = showOnInit !== false;
    VPort.send({ handler: "initInnerCSS" }, this.InitInner);
    this.init && this.init(false);
    this.box.style.display = "none";
    this.root = this.box.createShadowRoot();
    this.root.appendChild(element);
    this.addElement = function(element) {
      this.root.appendChild(element);
      this.adjust();
    };
  },
  addElementList: function(els, id, offset) {
    var parent, _i, _len, style;
    parent = VDom.createElement("div");
    parent.className = "R LS";
    parent.id = id;
    for (_i = 0, _len = els.length; _i < _len; _i++) {
      parent.appendChild(els[_i]);
    }
    style = parent.style;
    style.left = offset[0] + "px"; style.top = offset[1] + "px";
    (_i = VDom.bodyZoom) !== 1 && (style.zoom = _i);
    document.webkitIsFullScreen && (style.position = "fixed");
    this.addElement(parent);
    return parent;
  },
  adjust: function() {
    var el = this.InitInner ? null : document.webkitFullscreenElement;
    (el && !this.root.contains(el) ? el : document.documentElement).appendChild(this.box);
  },
  init: function(showing) {
    this.box = VDom.createElement("vimium");
    showing !== false && this.adjust();
    this.init = null;
  },
  InitInner: function(innerCSS) {
    var _this = VDom.UI;
    _this.InitInner = null;
    _this.styleIn = _this.createStyle(innerCSS);
    _this.root.insertBefore(_this.styleIn, _this.root.firstElementChild);
    _this.showing && setTimeout(function() {
      _this.box.style.display = "";
      var el = _this.focusedEl; _this.focusedEl = null;
      el && setTimeout(function() { el.focus(); }, 17);
    }, 17);
    _this.adjust();
  },
  toggle: function(enabled) {
    if (!enabled) { this.box.remove(); return; }
    this.box.parentNode || this.adjust();
  },
  createStyle: function(text, doc) {
    var css = (doc || VDom).createElement("style");
    css.type = "text/css";
    css.textContent = text;
    return css;
  },
  InsertInnerCSS: function(inner) {
    VDom.UI.styleIn && (VDom.UI.styleIn.textContent = inner.css);
  },
  insertCSS: function(outer) {
    var el = this.styleOut;
    if (!outer) { el && el.remove(); return; }
    el ? (el.textContent = outer) : (el = this.styleOut = this.createStyle(outer));
    this.init && this.init();
    this.box.appendChild(el);
  },
  getSelection: function() {
    var sel = window.getSelection(), el, el2;
    if (sel.focusNode === document.documentElement && (el = VScroller.current)) {
      for (; el2 = el.parentNode; el = el2) {}
      if (el.getSelection) { sel = el.getSelection() || sel; }
    }
    return sel;
  },
  removeSelection: function(root) {
    var sel = (root || this.root).getSelection();
    if (sel.type !== "Range" || !sel.anchorNode) {
      return false;
    }
    sel.removeAllRanges();
    return true;
  },
  simulateSelect: function(element, flash, suppressRepeated) {
    element.focus();
    VDom.simulateClick(element);
    flash === true && this.flash(element);
    if (element !== VEventMode.lock()) { return; }
    var len;
    if ((len = element.value ? element.value.length : -1) && element.setSelectionRange) {
      if (element instanceof HTMLInputElement || element.clientHeight + 12 >= element.scrollHeight)
      try {
        if (0 == element.selectionEnd) {
          element.setSelectionRange(len, len);
        }
      } catch (e) {}
    }
    suppressRepeated === true && this.suppressTail(true);
  },
  focus: function(el) {
    if (this.box.style.display) {
      this.focusedEl = el;
    } else {
      el.focus();
    }
  },
  getVRect: function(clickEl) {
    var rect, bcr, b = document.body;
    VDom.prepareCrop();
    VDom.bodyZoom = b && VDom.isInDOM(clickEl, b) && +getComputedStyle(b).zoom || 1;
    rect = VDom.getVisibleClientRect(clickEl);
    bcr = VRect.fromClientRect(clickEl.getBoundingClientRect());
    return rect && !VRect.isContaining(bcr, rect) ? rect
      : VDom.isVisibile(clickEl) ? bcr : null;
  },
  flash: function(el, rect) {
    rect || (rect = this.getVRect(el));
    if (!rect) { return; }
    var flashEl = VDom.createElement("div"), nfs = !document.webkitIsFullScreen;
    flashEl.className = "R Flash";
    VRect.setBoundary(flashEl.style, rect, nfs);
    VDom.bodyZoom !== 1 && nfs && (flashEl.style.zoom = VDom.bodyZoom);
    this.addElement(flashEl);
    return setTimeout(function() {
      flashEl.remove();
    }, this.flashLastingTime);
  },
  suppressTail: function(onlyRepeated) {
    var func, tick, timer;
    if (onlyRepeated) {
      func = function(event) {
        if (event.repeat) { return 2; }
        VHandler.remove(this);
        return 0;
      };
    } else {
      func = function() { tick = Date.now(); return 2; };
      tick = Date.now() + VSettings.cache.keyboard[0];
      timer = setInterval(function() {
        if (Date.now() - tick > 150) {
          clearInterval(timer);
          VHandler && VHandler.remove(func);
        }
      }, 75);
    }
    VHandler.push(func, func);
  },
  SuppressMost: function(event) {
    var key = event.keyCode;
    if (VKeyboard.isEscape(event)) {
      VHandler.remove(this);
    }
    return key > VKeyCodes.f1 + 9 && key <= VKeyCodes.f12 ? 1 : 2;
  }
};
<|endoftext|>


<commit_before>
'use strict';

function comp (prev, next) {
  const prevIdx = index(prev);  // return as a Map
  const result = {
    addition: [],
    deletion: [],
    modified: []
  };
  for (let i = 0; i < next.length; i++) {
    const item = next[i];
    if (!item) continue
    const key = item[0];
    const val = JSON.stringify(item[1]);
    if (prevIdx.has(key)) {
      if (JSON.stringify(prevIdx.get(key)) !== val) {
        result.modified.push({
          key: key, val: item[1]
        });
      }
      // delete processed item
      prevIdx.delete(key);
    } else {
      result.addition.push({
        key: key, val: item[1]
      });
    }
  }
  if (prevIdx.size === 0) {
    return result;
  } else {
    prevIdx.forEach(function (val, key) {
      result.deletion.push({
        key: key, val: val
      });
    });
    return result;
  }
}

function index (arr) {
  const ret = new Map();
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];
    if (item) {
      const key = item[0];
      const val = item[1];
      ret.set(key, val);
    }
  }
  return ret;
}

function summary (result, older, ref, repo) {
  console.log(arguments);
  let text = '\nThe following are interface summary:\n';
  const refUrl = repo + '/tree/' + ref;
  const olderUrl = repo + '/tree/' + older;
  result.addition.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has added the remote method: \`${item.key}\``;
    text += '\n';
  });
  result.deletion.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has removed the remote method: \`${item.key}\``;
    text += `from [${older}](${olderUrl})\n`;
  });
  result.modified.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has modified the remote method: \`${item.key}\``;
    text += `from [${older}](${olderUrl})\n`;
  });
  return text
}

exports.comp = comp;
exports.index = index;
exports.summary = summary;
<commit_msg>tweak template<commit_after>
'use strict';

function comp (prev, next) {
  const prevIdx = index(prev);  // return as a Map
  const result = {
    addition: [],
    deletion: [],
    modified: []
  };
  for (let i = 0; i < next.length; i++) {
    const item = next[i];
    if (!item) continue
    const key = item[0];
    const val = JSON.stringify(item[1]);
    if (prevIdx.has(key)) {
      if (JSON.stringify(prevIdx.get(key)) !== val) {
        result.modified.push({
          key: key, val: item[1]
        });
      }
      // delete processed item
      prevIdx.delete(key);
    } else {
      result.addition.push({
        key: key, val: item[1]
      });
    }
  }
  if (prevIdx.size === 0) {
    return result;
  } else {
    prevIdx.forEach(function (val, key) {
      result.deletion.push({
        key: key, val: val
      });
    });
    return result;
  }
}

function index (arr) {
  const ret = new Map();
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];
    if (item) {
      const key = item[0];
      const val = item[1];
      ret.set(key, val);
    }
  }
  return ret;
}

function summary (result, older, ref, repo) {
  let text = '';
  const refUrl = repo + '/tree/' + ref;
  const olderUrl = repo + '/tree/' + older;
  result.addition.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has added the remote method: \`${item.key}\``;
    text += '\n';
  });
  result.deletion.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has removed the remote method: \`${item.key}\``;
    text += `from [${older}](${olderUrl})\n`;
  });
  result.modified.forEach(function (item) {
    text += `+ [${ref}](${refUrl}) has modified the remote method: \`${item.key}\``;
    text += `from [${older}](${olderUrl})\n`;
  });
  if (text.length !== 0) {
    text = 'The following are interface summary:\n' + text;
  }
  return text
}

exports.comp = comp;
exports.index = index;
exports.summary = summary;
<|endoftext|>


<commit_before>/*
 *  Copyright 2012 the original author or authors.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
dc = {
    version: "1.2.0",
    constants : {
        CHART_CLASS: "dc-chart",
        DEBUG_GROUP_CLASS: "debug",
        STACK_CLASS: "stack",
        DESELECTED_CLASS: "deselected",
        SELECTED_CLASS: "selected",
        NODE_INDEX_NAME: "__index__",
        GROUP_INDEX_NAME: "__group_index__",
        DEFAULT_CHART_GROUP: "__default_chart_group__",
        EVENT_DELAY: 40,
        NEGLIGIBLE_NUMBER: 1e-10
    },
    _renderlet : null
};

dc.chartRegistry = function() {
    // chartGroup:string => charts:array
    var _chartMap = {};

    this.has = function(chart) {
        for (var e in _chartMap) {
            if (_chartMap[e].indexOf(chart) >= 0)
                return true;
        }
        return false;
    };

    function initializeChartGroup(group) {
        if (!group)
            group = dc.constants.DEFAULT_CHART_GROUP;

        if (!_chartMap[group])
            _chartMap[group] = [];

        return group;
    }

    this.register = function(chart, group) {
        group = initializeChartGroup(group);
        _chartMap[group].push(chart);
    };

    this.clear = function() {
        _chartMap = {};
    };

    this.list = function(group) {
        group = initializeChartGroup(group);
        return _chartMap[group];
    };

    return this;
}();

dc.registerChart = function(chart, group) {
    dc.chartRegistry.register(chart, group);
};

dc.hasChart = function(chart) {
    return dc.chartRegistry.has(chart);
};

dc.deregisterAllCharts = function() {
    dc.chartRegistry.clear();
};

dc.filterAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].filterAll();
    }
};

dc.renderAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].render();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.redrawAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].redraw();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.transition = function(selections, duration, callback) {
    if (duration <= 0 || duration === undefined)
        return selections;

    var s = selections
        .transition()
        .duration(duration);

    if (callback instanceof Function) {
        callback(s);
    }

    return s;
};

dc.units = {};
dc.units.integers = function(s, e) {
    return Math.abs(e - s);
};

dc.units.ordinal = function(s, e, domain){
    return domain;
};
dc.units.float = {};
dc.units.float.precision= function(precision){
    var _f = function(s, e, domain){return Math.ceil(Math.abs((e-s)/_f.resolution));};
    _f.resolution = precision;
    return _f;
};

dc.round = {};
dc.round.floor = function(n) {
    return Math.floor(n);
};
dc.round.ceil = function(n) {
    return Math.ceil(n);
};
dc.round.round = function(n) {
    return Math.round(n);
};

dc.override = function(obj, functionName, newFunction) {
    var existingFunction = obj[functionName];
    obj["_" + functionName] = existingFunction;
    obj[functionName] = newFunction;
};

dc.renderlet = function(_){
    if(!arguments.length) return dc._renderlet;
    dc._renderlet = _;
    return dc;
};

dc.instanceOfChart = function (o) {
    return o instanceof Object && o.__dc_flag__;
};
<commit_msg>start v1.3 dev<commit_after>/*
 *  Copyright 2012 the original author or authors.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
dc = {
    version: "1.3.0",
    constants : {
        CHART_CLASS: "dc-chart",
        DEBUG_GROUP_CLASS: "debug",
        STACK_CLASS: "stack",
        DESELECTED_CLASS: "deselected",
        SELECTED_CLASS: "selected",
        NODE_INDEX_NAME: "__index__",
        GROUP_INDEX_NAME: "__group_index__",
        DEFAULT_CHART_GROUP: "__default_chart_group__",
        EVENT_DELAY: 40,
        NEGLIGIBLE_NUMBER: 1e-10
    },
    _renderlet : null
};

dc.chartRegistry = function() {
    // chartGroup:string => charts:array
    var _chartMap = {};

    this.has = function(chart) {
        for (var e in _chartMap) {
            if (_chartMap[e].indexOf(chart) >= 0)
                return true;
        }
        return false;
    };

    function initializeChartGroup(group) {
        if (!group)
            group = dc.constants.DEFAULT_CHART_GROUP;

        if (!_chartMap[group])
            _chartMap[group] = [];

        return group;
    }

    this.register = function(chart, group) {
        group = initializeChartGroup(group);
        _chartMap[group].push(chart);
    };

    this.clear = function() {
        _chartMap = {};
    };

    this.list = function(group) {
        group = initializeChartGroup(group);
        return _chartMap[group];
    };

    return this;
}();

dc.registerChart = function(chart, group) {
    dc.chartRegistry.register(chart, group);
};

dc.hasChart = function(chart) {
    return dc.chartRegistry.has(chart);
};

dc.deregisterAllCharts = function() {
    dc.chartRegistry.clear();
};

dc.filterAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].filterAll();
    }
};

dc.renderAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].render();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.redrawAll = function(group) {
    var charts = dc.chartRegistry.list(group);
    for (var i = 0; i < charts.length; ++i) {
        charts[i].redraw();
    }

    if(dc._renderlet !== null)
        dc._renderlet(group);
};

dc.transition = function(selections, duration, callback) {
    if (duration <= 0 || duration === undefined)
        return selections;

    var s = selections
        .transition()
        .duration(duration);

    if (callback instanceof Function) {
        callback(s);
    }

    return s;
};

dc.units = {};
dc.units.integers = function(s, e) {
    return Math.abs(e - s);
};

dc.units.ordinal = function(s, e, domain){
    return domain;
};
dc.units.float = {};
dc.units.float.precision= function(precision){
    var _f = function(s, e, domain){return Math.ceil(Math.abs((e-s)/_f.resolution));};
    _f.resolution = precision;
    return _f;
};

dc.round = {};
dc.round.floor = function(n) {
    return Math.floor(n);
};
dc.round.ceil = function(n) {
    return Math.ceil(n);
};
dc.round.round = function(n) {
    return Math.round(n);
};

dc.override = function(obj, functionName, newFunction) {
    var existingFunction = obj[functionName];
    obj["_" + functionName] = existingFunction;
    obj[functionName] = newFunction;
};

dc.renderlet = function(_){
    if(!arguments.length) return dc._renderlet;
    dc._renderlet = _;
    return dc;
};

dc.instanceOfChart = function (o) {
    return o instanceof Object && o.__dc_flag__;
};
<|endoftext|>


<commit_before>"use strict";
DomUtils.UI = {
  box: null,
  styleIn: null,
  styleOut: null,
  root: null,
  flashLastingTime: 400,
  addElement: function(element) {
    MainPort.sendMessage({ handler: "initInnerCSS" }, this.InitInner);
    this.init && this.init(false);
    this.box.style.display = "none";
    this.root = this.box.createShadowRoot();
    this.root.appendChild(element);
    this.addElement = function(element) {
      this.root.appendChild(element);
      this.adjust();
    };
  },
  addElementList: function(els, attrs) {
    var parent, _i, _len;
    parent = DomUtils.createElement("div");
    parent.className = attrs.className;
    parent.id = attrs.id;
    for (_i = 0, _len = els.length; _i < _len; _i++) {
      parent.appendChild(els[_i]);
    }
    this.addElement(parent);
    return parent;
  },
  adjust: function() {},
  init: function(showing) {
    this.box = DomUtils.createElement("vimium");
    showing !== false && document.documentElement.appendChild(this.box);
    this.init = null;
  },
  InitInner: function(innerCss) {
    var _this = DomUtils.UI;
    _this.InitInner = null;
    _this.styleIn = _this.createStyle(innerCss);
    _this.root.insertBefore(_this.styleIn, _this.root.firstElementChild);
    setTimeout(function() { var el = VInsertMode.heldEl; el && el.focus(); }, 17);
    _this.root.addEventListener("focusout", function(event) {
      if (VInsertMode.lock === event.target) {
        VInsertMode.lock = null;
      }
      event.target.focused = false;
    });
    _this.root.addEventListener("focusin", function(event) {
      var target;
      if (DomUtils.getEditableType(target = event.target)) {
        VInsertMode.lock = target;
        target.focused = true;
      }
    });
    _this.adjust = function() {
      (document.webkitFullscreenElement || document.documentElement).appendChild(this.box);
    };
    _this.adjust();
  },
  toggle: function(enabled) {
    this.box.style.display = enabled ? "" : "none";
    this.styleOut && (enabled ? this.box.appendChild(this.styleOut) : this.styleOut.remove());
  },
  createStyle: function(text, doc) {
    var css = (doc || DomUtils).createElement("style");
    css.type = "text/css";
    css.textContent = text;
    return css;
  },
  insertInnerCSS: function(inner) {
    this.styleIn && (this.styleIn.textContent = inner.css);
  },
  insertCSS: function(outer, showing) {
    var el;
    if (el = this.styleOut) {
      el.textContent = outer;
    } else {
      el = this.styleOut = this.createStyle(outer);
    }
    if (!showing) { el.remove(); return; }
    this.init && this.init();
    this.box.appendChild(el);
  },
  removeSelection: function(root) {
    var sel = (root || this.root).getSelection(), el, ind;
    if (sel.type !== "Range" || !sel.anchorNode) {
      return false;
    }
    if (!root && (el = VInsertMode.lock)) {
      ind = el.selectionDirection === "forward" && el.selectionEnd < el.value.length ?
          el.selectionStart : el.selectionEnd;
      el.setSelectionRange(ind, ind);
    } else {
      sel.removeAllRanges();
    }
    return true;
  },
  simulateSelect: function(element, flash, suppressRepeated) {
    element.focus();
    DomUtils.simulateClick(element);
    flash === true && this.flashVRect(this.getVRect(element));
    if (element !== VInsertMode.lock) { return; }
    var len;
    if ((len = element.value ? element.value.length : -1) && element.setSelectionRange) {
      if (element instanceof HTMLInputElement || element.clientHeight + 12 >= element.scrollHeight)
      try {
        if (0 == element.selectionEnd) {
          element.setSelectionRange(len, len);
        }
      } catch (e) {}
    }
    suppressRepeated === true && this.suppressTail(true);
  },
  getVRect: function(clickEl) {
    var rect, bcr;
    DomUtils.prepareCrop();
    if (clickEl.classList.contains("OIUrl") && Vomnibar.box
        && Vomnibar.box.contains(clickEl)) {
      rect = Vomnibar.computeHint(clickEl.parentElement.parentElement, clickEl);
    } else {
      rect = DomUtils.getVisibleClientRect(clickEl);
      bcr = VRect.fromClientRect(clickEl.getBoundingClientRect());
      if (!rect || VRect.isContaining(bcr, rect)) {
        rect = bcr;
      }
    }
    return rect;
  },
  flashVRect: function(rect, time) {
    var flashEl = DomUtils.createElement("div"), x, y;
    flashEl.className = "R Flash";
    if (rect[0] < 0 || rect[1] < 0 || rect[2] > window.innerWidth ||
        rect[3] > window.innerHeight) {
      x = window.scrollX; y = window.scrollY;
      flashEl.style.position = "absolute";
    } else {
      x = 0; y = 0;
    }
    flashEl.style.left = x + rect[0] + "px";
    flashEl.style.top = y + rect[1] + "px";
    flashEl.style.width = (rect[2] - rect[0]) + "px";
    flashEl.style.height = (rect[3] - rect[1]) + "px";
    this.addElement(flashEl);
    return setTimeout(function() {
      flashEl.remove();
    }, time || this.flashLastingTime);
  },
  suppressTail: function(onlyRepeated) {
    var func, tick, timer, func;
    if (onlyRepeated) {
      func = function(event) {
        if (event.repeat) { return 2; }
        handlerStack.remove(this);
        return 0;
      };
    } else {
      func = function() { tick = Date.now(); return 2; };
      tick = Date.now() + Settings.cache.keyboard[0];
      timer = setInterval(function() {
        if (Date.now() - tick > 150) {
          clearInterval(timer);
          handlerStack && handlerStack.remove(func);
        }
      }, 75);
    }
    handlerStack.push(func, func);
  },
  SuppressMost: function(event) {
    if (event.keyCode == KeyCodes.esc && KeyboardUtils.isPlain(event)) {
      handlerStack.remove(this);
    }
    return 2;
  }
};
<commit_msg>rework DomUtils.UI.toggle<commit_after>"use strict";
DomUtils.UI = {
  box: null,
  styleIn: null,
  styleOut: null,
  root: null,
  flashLastingTime: 400,
  addElement: function(element) {
    MainPort.sendMessage({ handler: "initInnerCSS" }, this.InitInner);
    this.init && this.init(false);
    this.box.style.display = "none";
    this.root = this.box.createShadowRoot();
    this.root.appendChild(element);
    this.addElement = function(element) {
      this.root.appendChild(element);
      this.adjust();
    };
  },
  addElementList: function(els, attrs) {
    var parent, _i, _len;
    parent = DomUtils.createElement("div");
    parent.className = attrs.className;
    parent.id = attrs.id;
    for (_i = 0, _len = els.length; _i < _len; _i++) {
      parent.appendChild(els[_i]);
    }
    this.addElement(parent);
    return parent;
  },
  adjust: function() {
    (!this.InitInner && document.webkitFullscreenElement || document.documentElement).appendChild(this.box);
  },
  init: function(showing) {
    this.box = DomUtils.createElement("vimium");
    showing !== false && this.adjust();
    this.init = null;
  },
  InitInner: function(innerCss) {
    var _this = DomUtils.UI;
    _this.InitInner = null;
    _this.styleIn = _this.createStyle(innerCss);
    _this.root.insertBefore(_this.styleIn, _this.root.firstElementChild);
    setTimeout(function() {
      _this.box.style.display = "";
      var el = VInsertMode.heldEl; el && el.focus();
    }, 17);
    _this.root.addEventListener("focusout", function(event) {
      if (VInsertMode.lock === event.target) {
        VInsertMode.lock = null;
      }
      event.target.focused = false;
    });
    _this.root.addEventListener("focusin", function(event) {
      var target;
      if (DomUtils.getEditableType(target = event.target)) {
        VInsertMode.lock = target;
        target.focused = true;
      }
    });
    _this.adjust();
  },
  toggle: function(enabled) {
    if (!enabled) { this.box.remove(); return; }
    this.box.parentNode || this.adjust();
  },
  createStyle: function(text, doc) {
    var css = (doc || DomUtils).createElement("style");
    css.type = "text/css";
    css.textContent = text;
    return css;
  },
  insertInnerCSS: function(inner) {
    this.styleIn && (this.styleIn.textContent = inner.css);
  },
  insertCSS: function(outer, showing) {
    var el;
    if (el = this.styleOut) {
      el.textContent = outer;
    } else {
      el = this.styleOut = this.createStyle(outer);
    }
    if (!showing) { el.remove(); return; }
    this.init && this.init();
    this.box.appendChild(el);
  },
  removeSelection: function(root) {
    var sel = (root || this.root).getSelection(), el, ind;
    if (sel.type !== "Range" || !sel.anchorNode) {
      return false;
    }
    if (!root && (el = VInsertMode.lock)) {
      ind = el.selectionDirection === "forward" && el.selectionEnd < el.value.length ?
          el.selectionStart : el.selectionEnd;
      el.setSelectionRange(ind, ind);
    } else {
      sel.removeAllRanges();
    }
    return true;
  },
  simulateSelect: function(element, flash, suppressRepeated) {
    element.focus();
    DomUtils.simulateClick(element);
    flash === true && this.flashVRect(this.getVRect(element));
    if (element !== VInsertMode.lock) { return; }
    var len;
    if ((len = element.value ? element.value.length : -1) && element.setSelectionRange) {
      if (element instanceof HTMLInputElement || element.clientHeight + 12 >= element.scrollHeight)
      try {
        if (0 == element.selectionEnd) {
          element.setSelectionRange(len, len);
        }
      } catch (e) {}
    }
    suppressRepeated === true && this.suppressTail(true);
  },
  getVRect: function(clickEl) {
    var rect, bcr;
    DomUtils.prepareCrop();
    if (clickEl.classList.contains("OIUrl") && Vomnibar.box
        && Vomnibar.box.contains(clickEl)) {
      rect = Vomnibar.computeHint(clickEl.parentElement.parentElement, clickEl);
    } else {
      rect = DomUtils.getVisibleClientRect(clickEl);
      bcr = VRect.fromClientRect(clickEl.getBoundingClientRect());
      if (!rect || VRect.isContaining(bcr, rect)) {
        rect = bcr;
      }
    }
    return rect;
  },
  flashVRect: function(rect, time) {
    var flashEl = DomUtils.createElement("div"), x, y;
    flashEl.className = "R Flash";
    if (rect[0] < 0 || rect[1] < 0 || rect[2] > window.innerWidth ||
        rect[3] > window.innerHeight) {
      x = window.scrollX; y = window.scrollY;
      flashEl.style.position = "absolute";
    } else {
      x = 0; y = 0;
    }
    flashEl.style.left = x + rect[0] + "px";
    flashEl.style.top = y + rect[1] + "px";
    flashEl.style.width = (rect[2] - rect[0]) + "px";
    flashEl.style.height = (rect[3] - rect[1]) + "px";
    this.addElement(flashEl);
    return setTimeout(function() {
      flashEl.remove();
    }, time || this.flashLastingTime);
  },
  suppressTail: function(onlyRepeated) {
    var func, tick, timer, func;
    if (onlyRepeated) {
      func = function(event) {
        if (event.repeat) { return 2; }
        handlerStack.remove(this);
        return 0;
      };
    } else {
      func = function() { tick = Date.now(); return 2; };
      tick = Date.now() + Settings.cache.keyboard[0];
      timer = setInterval(function() {
        if (Date.now() - tick > 150) {
          clearInterval(timer);
          handlerStack && handlerStack.remove(func);
        }
      }, 75);
    }
    handlerStack.push(func, func);
  },
  SuppressMost: function(event) {
    if (event.keyCode == KeyCodes.esc && KeyboardUtils.isPlain(event)) {
      handlerStack.remove(this);
    }
    return 2;
  }
};
<|endoftext|>


<commit_before>/*
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

var gRule;
var gMessages;
var gActions;

function init() {
  gRule = window.arguments[0] || {};
  if (gRule.name) {
    let title = document.documentElement.getAttribute('title-template');
    document.title = title.replace(/%s/i, gRule.name);
  }

  gMessages = document.getElementById('messages');
  gActions = document.getElementById('actions');

  Object.keys(gRule).forEach(function(aKey) {
    var value = gRule[aKey];
    var field = document.getElementById(aKey + '-field');
    if (field && value)
      field.value = value;
  });

  var actions = [];
  if (gRule.actions) {
    actions = JSON.parse(gRule.actions);
  } else if (gRule.action) {
    actions = [gRule.action];
  }

  actions.forEach(actionAdd);

  onGroupChanged();
  validateName();
}

function validateName() {
  var nameField = document.getElementById('name-field');
  var name = nameField.value;
  var accept = document.documentElement.getButton('accept');
  if (window.opener.isRuleDuplicated(name, gRule)) {
    accept.setAttribute('disabled', true);
    document.documentElement.setAttribute('validation-errors', 'duplicated-name');
    return false;
  } else if (name.trim() === '') {
    accept.setAttribute('disabled', true);
    document.documentElement.setAttribute('validation-errors', 'blank-name');
    return false;
  } else {
    accept.removeAttribute('disabled');
    document.documentElement.removeAttribute('validation-errors');
    return true;
  }
}

function onGroupChanged() {
  var group = document.getElementById('group-field').value;
  document.documentElement.setAttribute('group-type', group);
}

function captureActualOperation(aAction) {
  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                          .getService(Components.interfaces.nsIPromptService);
  var type = document.getElementById('type-field');
  console.log(type.value);
  var title = gMessages.getString('config.edit.capture.dialog.title');
  var description = gMessages.getString('config.edit.capture.dialog.description');
  var checkboxLabel = gMessages.getString('config.edit.capture.dialog.checkbox');
  var checked = {value: false};
  var buttonLabels = [];
  buttonLabels[0] = gMessages.getString('config.edit.capture.dialog.button.0');
  buttonLabels[1] = gMessages.getString('config.edit.capture.dialog.button.1');
  buttonLabels[2] = gMessages.getString('config.edit.capture.dialog.button.2');

  switch (type.value) {
  case 'alert':
    prompts.alertCheck(window,
                       title,
                       description,
                       checkboxLabel,
                       checked);
    if (checked.value) {
      actionAdd('check');
    }
    actionAdd('accept');
    break;
  case 'confirm':
    var result = prompts.confirmCheck(window,
                                      title,
                                      description,
                                      checkboxLabel,
                                      checked);
    console.log(result);
    if (checked.value) {
      actionAdd('check');
    }
    if (result) {
      actionAdd('accept');
    } else {
      actionAdd('cancel');
    }
    break;
  case 'confirmEx':
    var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_IS_STRING +
                prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_IS_STRING  +
                prompts.BUTTON_POS_2 * prompts.BUTTON_TITLE_IS_STRING;
    var pressedButtonIndex = prompts.confirmEx(window,
                                               title,
                                               description,
                                               flags,
                                               buttonLabels[0],
                                               buttonLabels[1],
                                               buttonLabels[2],
                                               null,
                                               checked);
    console.log(pressedButtonIndex);
    if (checked.value) {
      actionAdd('check');
    }
    actionAdd('push;' + buttonLabels[pressedButtonIndex]);
    break;
  case 'prompt':
    var result = prompt();
    console.log(result);
    if (result === null) {
      actionAdd('cancel');
    } else {
      actionAdd('input;' + result);
      actionAdd('accept');
    }
    break;
  case 'select':
    // TODO
    //select();
    break;
  }
}

function actionAdd(aAction) {
  var template = document.getElementById('action-item-template');
  var item = template.cloneNode(true);
  item.removeAttribute('id');
  gActions.insertBefore(item, gActions.lastChild);

  aAction = aAction || '';
  var matched = aAction.match(/^([^;]+)(?:;(.*)$)?/);
  if (!matched)
    return;

  var name = matched[1];
  var params = matched[2];
  if (name)
    item.querySelector('.action-name-field').value = name;
  if (params)
    item.querySelector('.action-params-field').value = params;
}

function actionUp(aItem) {
  if (aItem == gActions.firstChild)
    return;
  gActions.insertBefore(aItem, aItem.previousSibling);
}

function actionDown(aItem) {
  if (aItem.nextSibling == gActions.lastChild)
    return;
  gActions.insertBefore(aItem, aItem.nextSibling.nextSibling);
}

function actionDelete(aItem) {
  gActions.removeChild(aItem);
}

function serializeAction(aItem) {
  var nameField = aItem.querySelector('.action-name-field');
  var paramsField = aItem.querySelector('.action-params-field');
  if (paramsField.clientWidth > 0 &&
      paramsField.clientHeight > 0 &&
      paramsField.value) {
    return nameField.value + ';' + paramsField.value;
  } else {
    return nameField.value;
  }
}

function onAccept() {
  ['name',
   'group',
   'type',
   'url',
   'title',
   'text'].forEach(function(aProperty) {
    gRule[aProperty] = document.getElementById(aProperty + '-field').value;
  });
  switch (gRule.group) {
  case 'common':
    gRule.url = '';
    break;
  case 'general':
    gRule.type = '';
    break;
  }

  var actions = document.querySelectorAll('#actions richlistitem.action');
  if (actions.length === 0) {
    gRule.actions = gRule.action = '';
  } else if (actions.length == 1) {
    gRule.actions = '';
    gRule.action = serializeAction(actions[0]);
  } else {
    gRule.action = '';
    gRule.actions = JSON.stringify(Array.map(actions, serializeAction));
  }

  gRule.changed = true;

  return true;
}
<commit_msg>Implement prompt()<commit_after>/*
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

var gRule;
var gMessages;
var gActions;

function init() {
  gRule = window.arguments[0] || {};
  if (gRule.name) {
    let title = document.documentElement.getAttribute('title-template');
    document.title = title.replace(/%s/i, gRule.name);
  }

  gMessages = document.getElementById('messages');
  gActions = document.getElementById('actions');

  Object.keys(gRule).forEach(function(aKey) {
    var value = gRule[aKey];
    var field = document.getElementById(aKey + '-field');
    if (field && value)
      field.value = value;
  });

  var actions = [];
  if (gRule.actions) {
    actions = JSON.parse(gRule.actions);
  } else if (gRule.action) {
    actions = [gRule.action];
  }

  actions.forEach(actionAdd);

  onGroupChanged();
  validateName();
}

function validateName() {
  var nameField = document.getElementById('name-field');
  var name = nameField.value;
  var accept = document.documentElement.getButton('accept');
  if (window.opener.isRuleDuplicated(name, gRule)) {
    accept.setAttribute('disabled', true);
    document.documentElement.setAttribute('validation-errors', 'duplicated-name');
    return false;
  } else if (name.trim() === '') {
    accept.setAttribute('disabled', true);
    document.documentElement.setAttribute('validation-errors', 'blank-name');
    return false;
  } else {
    accept.removeAttribute('disabled');
    document.documentElement.removeAttribute('validation-errors');
    return true;
  }
}

function onGroupChanged() {
  var group = document.getElementById('group-field').value;
  document.documentElement.setAttribute('group-type', group);
}

function captureActualOperation(aAction) {
  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                          .getService(Components.interfaces.nsIPromptService);
  var type = document.getElementById('type-field');
  console.log(type.value);
  var title = gMessages.getString('config.edit.capture.dialog.title');
  var description = gMessages.getString('config.edit.capture.dialog.description');
  var checkboxLabel = gMessages.getString('config.edit.capture.dialog.checkbox');
  var checked = {value: false};
  var inputMessage = {value: ''};
  var buttonLabels = [];
  buttonLabels[0] = gMessages.getString('config.edit.capture.dialog.button.0');
  buttonLabels[1] = gMessages.getString('config.edit.capture.dialog.button.1');
  buttonLabels[2] = gMessages.getString('config.edit.capture.dialog.button.2');

  switch (type.value) {
  case 'alert':
    prompts.alertCheck(window,
                       title,
                       description,
                       checkboxLabel,
                       checked);
    if (checked.value) {
      actionAdd('check');
    }
    actionAdd('accept');
    break;
  case 'confirm':
    var result = prompts.confirmCheck(window,
                                      title,
                                      description,
                                      checkboxLabel,
                                      checked);
    console.log(result);
    if (checked.value) {
      actionAdd('check');
    }
    if (result) {
      actionAdd('accept');
    } else {
      actionAdd('cancel');
    }
    break;
  case 'confirmEx':
    var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_IS_STRING +
                prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_IS_STRING  +
                prompts.BUTTON_POS_2 * prompts.BUTTON_TITLE_IS_STRING;
    var pressedButtonIndex = prompts.confirmEx(window,
                                               title,
                                               description,
                                               flags,
                                               buttonLabels[0],
                                               buttonLabels[1],
                                               buttonLabels[2],
                                               null,
                                               checked);
    console.log(pressedButtonIndex);
    if (checked.value) {
      actionAdd('check');
    }
    actionAdd('push;' + buttonLabels[pressedButtonIndex]);
    break;
  case 'prompt':
    var result = prompts.prompt(window,
                                title,
                                description,
                                inputMessage,
                                checkboxLabel,
                                checked);
    console.log(result);
    if (inputMessage.value) {
      actionAdd('input;' + inputMessage.value);
    }
    if (checked.value) {
      actionAdd('check');
    }
    if (result) {
      actionAdd('accept');
    } else {
      actionAdd('cancel');
    }
    break;
  case 'select':
    // TODO
    //select();
    break;
  }
}

function actionAdd(aAction) {
  var template = document.getElementById('action-item-template');
  var item = template.cloneNode(true);
  item.removeAttribute('id');
  gActions.insertBefore(item, gActions.lastChild);

  aAction = aAction || '';
  var matched = aAction.match(/^([^;]+)(?:;(.*)$)?/);
  if (!matched)
    return;

  var name = matched[1];
  var params = matched[2];
  if (name)
    item.querySelector('.action-name-field').value = name;
  if (params)
    item.querySelector('.action-params-field').value = params;
}

function actionUp(aItem) {
  if (aItem == gActions.firstChild)
    return;
  gActions.insertBefore(aItem, aItem.previousSibling);
}

function actionDown(aItem) {
  if (aItem.nextSibling == gActions.lastChild)
    return;
  gActions.insertBefore(aItem, aItem.nextSibling.nextSibling);
}

function actionDelete(aItem) {
  gActions.removeChild(aItem);
}

function serializeAction(aItem) {
  var nameField = aItem.querySelector('.action-name-field');
  var paramsField = aItem.querySelector('.action-params-field');
  if (paramsField.clientWidth > 0 &&
      paramsField.clientHeight > 0 &&
      paramsField.value) {
    return nameField.value + ';' + paramsField.value;
  } else {
    return nameField.value;
  }
}

function onAccept() {
  ['name',
   'group',
   'type',
   'url',
   'title',
   'text'].forEach(function(aProperty) {
    gRule[aProperty] = document.getElementById(aProperty + '-field').value;
  });
  switch (gRule.group) {
  case 'common':
    gRule.url = '';
    break;
  case 'general':
    gRule.type = '';
    break;
  }

  var actions = document.querySelectorAll('#actions richlistitem.action');
  if (actions.length === 0) {
    gRule.actions = gRule.action = '';
  } else if (actions.length == 1) {
    gRule.actions = '';
    gRule.action = serializeAction(actions[0]);
  } else {
    gRule.action = '';
    gRule.actions = JSON.stringify(Array.map(actions, serializeAction));
  }

  gRule.changed = true;

  return true;
}
<|endoftext|>