<commit_before>// Raven.js
//
// Originally based on the Arecibo JavaScript client.
//
// Requires:
//     * TraceKit
//     * parseUri (included in the full and minified distribution files)

;(function(window, undefined){

'use strict';

// First, check for JSON support
// If there is no JSON, we no-op the core features of Raven
// since JSON is required to encode the payload
var hasJSON = typeof(window.JSON) !== 'undefined',
    globalOptions = {
        publicKey: undefined,  // Leave as undefined if not using project auth
        servers: [],
        projectId: 1,
        logger: 'javascript',
        site: undefined,
        dataCallback: null,
        ignoreErrors: [],
        ignoreUrls: []
    };

/*
 * The core Raven object
 */
var Raven = {
    VERSION: '@VERSION',

    /*
     * Raven.config()
     *
     * Configure raven with a DSN or config object
     */
    config: function(config) {
        var servers = [];

        if (typeof(config) === 'string') {
            config = parseDSN(config);
        }

        each(config, function(key, option) {
            globalOptions[key] = option;
        });

        // Expand server base URLs into API URLs
        each(globalOptions.servers, function(i, server) {
            // Add a trailing slash if one isn't provided
            if (server.slice(-1) !== '/') {
                server += '/';
            }
            servers.push(server + 'api/' + globalOptions.projectId + '/store/');
        });
        globalOptions.servers = servers;

        // "Script error."" is hard coded into browsers for errors that it can't read.
        // this is the result of a script being pulled in from an external domain and CORS.
        globalOptions.ignoreErrors.push('Script error.');

        return this;
    },

    /*
     * Raven.install()
     *
     * Installs a global window.onerror error handler
     * to capture and report uncaught exceptions.
     */
    install: function() {
        if (!hasJSON) return;  // no sense installing without JSON support

        TraceKit.report.subscribe(handleStackInfo);
    },

    /*
     * Raven.captureException()
     *
     * Manually capture an exception and send it over to Sentry
     */
    captureException: function(ex) {
        // TraceKit.report will re-raise any exception passed to it,
        // which means you have to wrap it in try/catch. Instead, we
        // can wrap it here and only re-raise if TraceKit.report
        // raises an exception different from the one we asked to
        // report on.
        try {
            TraceKit.report(ex);
        } catch(ex1) {
            if(ex !== ex1) {
                throw ex1;
            }
        }
    },

    /*
     * Raven.captureMessage()
     *
     * Manually send a message to Sentry
     */
    captureMessage: function(msg, options) {
        // Fire away!
        send(
            arrayMerge({
                message: msg
            }, options)
        );
    }
};

/**** Private functions ****/
function parseUri(str) {
    var keys = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' '),
        m = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(str),
        uri = {},
        i = 14;

    while (i--) uri[keys[i]] = m[i] || '';

    return uri;
}

function each(obj, callback) {
    var i, j;

    if (obj.length === undefined) {
        for (i in obj) {
            if (obj.hasOwnProperty(i)) {
                callback.call(null, i, obj[i]);
            }
        }
    } else {
        for (i = 0, j = obj.length; i < j; i++) {
            callback.call(null, i, obj[i]);
        }
    }
}

function parseDSN(dsn) {
    var uri = parseUri(dsn),
        path_idx = uri.path.lastIndexOf('/'),
        project_id,
        path;

    if (path_idx === -1) {
        project_id = uri.path.substr(1);
        path = '';
    } else {
        path = uri.path.substr(1, path_idx);
        project_id = uri.path.substr(path_idx + 1);
    }

    return {
        servers: [uri.protocol + '://' + uri.host + (uri.port ? ':' + uri.port : '') + '/' + path],
        publicKey: uri.user,
        projectId: project_id
    };
}

function getAuthQueryString(timestamp) {
    var qs = [
        'sentry_version=2.0',
        'sentry_timestamp=' + timestamp,
        'sentry_client=raven-js/' + Raven.VERSION
    ];
    if (globalOptions.publicKey) {
        qs.push('sentry_key=' + globalOptions.publicKey);
    }
    return '?' + qs.join('&');
}

function handleStackInfo(stackInfo, options) {
    var frames = [], pivot, context, i, j, ii, jj, currentStack, currentFrame;

    for (i = 0, j = stackInfo.stack.length; i < j; i++) {
        // normalize the frames data
        currentStack = stackInfo.stack[i];
        currentFrame = {
            abs_path:   currentStack.url,
            filename:   currentStack.url.split(/\/([^\/]+)$/)[1] || currentStack.url, // extract the filename
            lineno:     currentStack.line,
            'function': currentStack.func
        };

        if (currentStack.context) {
            context = currentStack.context;
            for(ii = 0, jj = context.length; ii < jj; ii++) {
                if (context[ii].length > 150) context[ii] = '...truncated...';
            }
            pivot = ~~(context.length / 2);
            currentFrame.pre_context = context.slice(0, pivot);
            currentFrame.context_line = context[pivot];
            currentFrame.post_context = context.slice(pivot + 1);
        }

        frames[i] = currentFrame;
    }
    processException(
        stackInfo.name,
        stackInfo.message,
        stackInfo.url,
        stackInfo.lineno,
        frames,
        options
    );
}

function processException(type, message, fileurl, lineno, frames, options) {
    var stacktrace, label, i, j;

    for (i = 0, j = globalOptions.ignoreErrors.length; i < j; i++) {
        if (message === globalOptions.ignoreErrors[i]) {
            return;
        }
    }

    if (frames) {
        stacktrace = {frames: frames};
        fileurl = fileurl || frames[0].filename;
    } else if (fileurl) {
        stacktrace = {
            frames: [{
                filename: fileurl,
                lineno: lineno
            }]
        };
    }

    for (i = 0, j = globalOptions.ignoreUrls.length; i < j; i++) {
        if (globalOptions.ignoreUrls[i].test(fileurl)) {
            return;
        }
    }

    label = lineno ? message + ' at ' + lineno : message;

    // Fire away!
    send(
        arrayMerge({
            'sentry.interfaces.Exception': {
                type: type,
                value: message
            },
            'sentry.interfaces.Stacktrace': stacktrace,
            culprit: fileurl,
            message: label
        }, options)
    );
}

function arrayMerge(arr1, arr2) {
    if (typeof(arr2) === 'undefined') {
        return arr1;
    }
    each(arr2, function(key, value){
        arr1[key] = value;
    });
    return arr1;
}

function pad(n, amount) {
    var i,
        len = ('' + n).length;
    if (typeof(amount) === 'undefined') {
        amount = 2;
    }
    if (len >= amount) {
        return n;
    }
    for (i=0; i < (amount - len); i++) {
        n = '0' + n;
    }
    return n;
}

function dateToISOString(date) {
    if (Date.prototype.toISOString) {
        return date.toISOString();
    }

    return date.getUTCFullYear() + '-' +
        pad(date.getUTCMonth() + 1) + '-' +
        pad(date.getUTCDate()) + 'T' +
        pad(date.getUTCHours()) + ':' +
        pad(date.getUTCMinutes()) + ':' +
        pad(date.getUTCSeconds()) + '.' +
        pad(date.getUTCMilliseconds(), 3) + 'Z';
}

function send(data) {
    if (!hasJSON) return;  // needs JSON support

    var encoded_msg,
        now = new Date(),
        url = window.location.protocol + '//' + window.location.host + window.location.pathname,
        querystring = window.location.search.slice(1),  // Remove the ?
        auth = getAuthQueryString(now.getTime());

    data = arrayMerge({
        project: globalOptions.projectId,
        logger: globalOptions.logger,
        site: globalOptions.site,
        timestamp: dateToISOString(now),
        platform: 'javascript',
        'sentry.interfaces.Http': {
            url: url,
            querystring: querystring
        }
    }, data);

    if (typeof(globalOptions.dataCallback) === 'function') {
        data = globalOptions.dataCallback(data);
    }

    encoded_msg = '&sentry_data=' + encodeURIComponent(JSON.stringify(data));

    each(globalOptions.servers, function (i, server) {
        new Image().src = server + auth + encoded_msg;
    });
}

// Expose Raven to the world
window.Raven = Raven;

})(window);
<commit_msg>No more timestamps<commit_after>// Raven.js
//
// Originally based on the Arecibo JavaScript client.
//
// Requires:
//     * TraceKit
//     * parseUri (included in the full and minified distribution files)

;(function(window, undefined){

'use strict';

// First, check for JSON support
// If there is no JSON, we no-op the core features of Raven
// since JSON is required to encode the payload
var hasJSON = typeof(window.JSON) !== 'undefined',
    globalOptions = {
        publicKey: undefined,  // Leave as undefined if not using project auth
        servers: [],
        projectId: 1,
        logger: 'javascript',
        site: undefined,
        dataCallback: null,
        ignoreErrors: [],
        ignoreUrls: []
    };

/*
 * The core Raven object
 */
var Raven = {
    VERSION: '@VERSION',

    /*
     * Raven.config()
     *
     * Configure raven with a DSN or config object
     */
    config: function(config) {
        var servers = [];

        if (typeof(config) === 'string') {
            config = parseDSN(config);
        }

        each(config, function(key, option) {
            globalOptions[key] = option;
        });

        // Expand server base URLs into API URLs
        each(globalOptions.servers, function(i, server) {
            // Add a trailing slash if one isn't provided
            if (server.slice(-1) !== '/') {
                server += '/';
            }
            servers.push(server + 'api/' + globalOptions.projectId + '/store/');
        });
        globalOptions.servers = servers;

        // "Script error."" is hard coded into browsers for errors that it can't read.
        // this is the result of a script being pulled in from an external domain and CORS.
        globalOptions.ignoreErrors.push('Script error.');

        return this;
    },

    /*
     * Raven.install()
     *
     * Installs a global window.onerror error handler
     * to capture and report uncaught exceptions.
     */
    install: function() {
        if (!hasJSON) return;  // no sense installing without JSON support

        TraceKit.report.subscribe(handleStackInfo);
    },

    /*
     * Raven.captureException()
     *
     * Manually capture an exception and send it over to Sentry
     */
    captureException: function(ex) {
        // TraceKit.report will re-raise any exception passed to it,
        // which means you have to wrap it in try/catch. Instead, we
        // can wrap it here and only re-raise if TraceKit.report
        // raises an exception different from the one we asked to
        // report on.
        try {
            TraceKit.report(ex);
        } catch(ex1) {
            if(ex !== ex1) {
                throw ex1;
            }
        }
    },

    /*
     * Raven.captureMessage()
     *
     * Manually send a message to Sentry
     */
    captureMessage: function(msg, options) {
        // Fire away!
        send(
            arrayMerge({
                message: msg
            }, options)
        );
    }
};

/**** Private functions ****/
function parseUri(str) {
    var keys = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' '),
        m = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(str),
        uri = {},
        i = 14;

    while (i--) uri[keys[i]] = m[i] || '';

    return uri;
}

function each(obj, callback) {
    var i, j;

    if (obj.length === undefined) {
        for (i in obj) {
            if (obj.hasOwnProperty(i)) {
                callback.call(null, i, obj[i]);
            }
        }
    } else {
        for (i = 0, j = obj.length; i < j; i++) {
            callback.call(null, i, obj[i]);
        }
    }
}

function parseDSN(dsn) {
    var uri = parseUri(dsn),
        path_idx = uri.path.lastIndexOf('/'),
        project_id,
        path;

    if (path_idx === -1) {
        project_id = uri.path.substr(1);
        path = '';
    } else {
        path = uri.path.substr(1, path_idx);
        project_id = uri.path.substr(path_idx + 1);
    }

    return {
        servers: [uri.protocol + '://' + uri.host + (uri.port ? ':' + uri.port : '') + '/' + path],
        publicKey: uri.user,
        projectId: project_id
    };
}

function getAuthQueryString() {
    var qs = [
        'sentry_version=2.0',
        'sentry_client=raven-js/' + Raven.VERSION
    ];
    if (globalOptions.publicKey) {
        qs.push('sentry_key=' + globalOptions.publicKey);
    }
    return '?' + qs.join('&');
}

function handleStackInfo(stackInfo, options) {
    var frames = [], pivot, context, i, j, ii, jj, currentStack, currentFrame;

    for (i = 0, j = stackInfo.stack.length; i < j; i++) {
        // normalize the frames data
        currentStack = stackInfo.stack[i];
        currentFrame = {
            abs_path:   currentStack.url,
            filename:   currentStack.url.split(/\/([^\/]+)$/)[1] || currentStack.url, // extract the filename
            lineno:     currentStack.line,
            'function': currentStack.func
        };

        if (currentStack.context) {
            context = currentStack.context;
            for(ii = 0, jj = context.length; ii < jj; ii++) {
                if (context[ii].length > 150) context[ii] = '...truncated...';
            }
            pivot = ~~(context.length / 2);
            currentFrame.pre_context = context.slice(0, pivot);
            currentFrame.context_line = context[pivot];
            currentFrame.post_context = context.slice(pivot + 1);
        }

        frames[i] = currentFrame;
    }
    processException(
        stackInfo.name,
        stackInfo.message,
        stackInfo.url,
        stackInfo.lineno,
        frames,
        options
    );
}

function processException(type, message, fileurl, lineno, frames, options) {
    var stacktrace, label, i, j;

    for (i = 0, j = globalOptions.ignoreErrors.length; i < j; i++) {
        if (message === globalOptions.ignoreErrors[i]) {
            return;
        }
    }

    if (frames) {
        stacktrace = {frames: frames};
        fileurl = fileurl || frames[0].filename;
    } else if (fileurl) {
        stacktrace = {
            frames: [{
                filename: fileurl,
                lineno: lineno
            }]
        };
    }

    for (i = 0, j = globalOptions.ignoreUrls.length; i < j; i++) {
        if (globalOptions.ignoreUrls[i].test(fileurl)) {
            return;
        }
    }

    label = lineno ? message + ' at ' + lineno : message;

    // Fire away!
    send(
        arrayMerge({
            'sentry.interfaces.Exception': {
                type: type,
                value: message
            },
            'sentry.interfaces.Stacktrace': stacktrace,
            culprit: fileurl,
            message: label
        }, options)
    );
}

function arrayMerge(arr1, arr2) {
    if (typeof(arr2) === 'undefined') {
        return arr1;
    }
    each(arr2, function(key, value){
        arr1[key] = value;
    });
    return arr1;
}

function send(data) {
    if (!hasJSON) return;  // needs JSON support

    var encoded_msg,
        url = window.location.protocol + '//' + window.location.host + window.location.pathname,
        querystring = window.location.search.slice(1),  // Remove the ?
        auth = getAuthQueryString();

    data = arrayMerge({
        project: globalOptions.projectId,
        logger: globalOptions.logger,
        site: globalOptions.site,
        platform: 'javascript',
        'sentry.interfaces.Http': {
            url: url,
            querystring: querystring
        }
    }, data);

    if (typeof(globalOptions.dataCallback) === 'function') {
        data = globalOptions.dataCallback(data);
    }

    encoded_msg = '&sentry_data=' + encodeURIComponent(JSON.stringify(data));

    each(globalOptions.servers, function (i, server) {
        new Image().src = server + auth + encoded_msg;
    });
}

// Expose Raven to the world
window.Raven = Raven;

})(window);
<|endoftext|>


<commit_before>'use strict';

const fs = require( 'fs' );
const svm = require( 'node-svm' );
const _ = require( 'lodash' );
const util = require( 'util' );

var data = require( '../model/data' );

var dataset = data.features.map( (e, i) => {
    var o = [];
    o[0] = e;
    o[1] = data.sentiments[i];
    return o;
});

var clf = new svm.CSVC({
    kernelType: 'linear',
    probability: true,
    c:[0.005, 0.01,0.125,0.5,1,2]
});

clf.train(dataset)
    .progress( function( rate ) {
        console.log( rate );
    })
    .spread( (trainedModel, trainingReport) => {
        console.log(trainingReport);
        fs.writeFileSync( path.normalize( __dirname + '/../model/model.json' ), JSON.stringify(trainedModel) );
    });
<commit_msg>[FIX] path dep in train.js<commit_after>'use strict';

const fs = require( 'fs' );
const svm = require( 'node-svm' );
const _ = require( 'lodash' );
const util = require( 'util' );
const path = require( 'path' );

var data = require( '../model/data' );

var dataset = data.features.map( (e, i) => {
    var o = [];
    o[0] = e;
    o[1] = data.sentiments[i];
    return o;
});

var clf = new svm.CSVC({
    kernelType: 'linear',
    probability: true,
    c:[0.005, 0.01,0.125,0.5,1,2]
});

clf.train(dataset)
    .progress( function( rate ) {
        console.log( rate );
    })
    .spread( (trainedModel, trainingReport) => {
        console.log(trainingReport);
        fs.writeFileSync( path.normalize( __dirname + '/../model/model.json' ), JSON.stringify(trainedModel) );
    });
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use babel';
'use strict';

import bot from './bot';
import config from './config';
import version from './version';
import * as db from './database';
import Character from './database/character';
import * as analytics from './util/analytics';
import DiceExpression from 'dice-expression-evaluator';

import ListCharactersCommand from './commands/characters/list';
import ViewCharacterCommand from './commands/characters/view';
import AddCharacterCommand from './commands/characters/add';
import DeleteCharacterCommand from './commands/characters/delete';
import ClearCharactersCommand from './commands/characters/clear';
import RollDiceCommand from './commands/dice/roll';
import MaxRollCommand from './commands/dice/max';
import MinRollCommand from './commands/dice/min';

bot.logger.info(`RPBot v${version} is starting...`);
analytics.sendEvent('Bot', 'started');

// Create bot
export const client = bot
	.registerDefaults()
	.registerModules([
		['characters', 'Characters'],
		['dice', 'Dice']
	])
	.registerCommands([
		ListCharactersCommand,
		ViewCharacterCommand,
		AddCharacterCommand,
		DeleteCharacterCommand,
		ClearCharactersCommand,
		RollDiceCommand,
		MaxRollCommand,
		MinRollCommand
	])
	.registerEvalObjects({
		db: db,
		Character: Character,
		config: config,
		version: version,
		dice: DiceExpression
	})
.createClient();

// Set up database
db.init().catch(err => {
	bot.logger.error(err);
	process.exit(1);
});

// Set up Carbonitex guild count updates
if(config.carbonURL) {
	const request = require('request-promise-native');
	const sendCarbon = () => {
		request({
			method: 'POST',
			uri: config.carbonURL,
			body: {
				key: config.carbonKey,
				servercount: client.guilds.size
			},
			json: true
		}).then(() => {
			bot.logger.info(`Sent guild count to Carbon with ${client.guilds.size} guilds.`);
		}).catch(err => {
			bot.logger.error('Error while sending guild count to Carbon.', err);
		});
	};
	client.once('ready', sendCarbon);
	client.on('guildCreate', sendCarbon);
	client.on('guildDelete', sendCarbon);
}

// Exit on interrupt
let interruptCount = 0;
process.on('SIGINT', async () => {
	interruptCount++;
	if(interruptCount === 1) {
		bot.logger.info('Received interrupt signal; closing database, destroying client, and exiting...');
		await Promise.all([
			db.close(),
			client.destroy()
		]).catch(err => {
			bot.logger.error(err);
		});
		process.exit(0);
	} else {
		bot.logger.info('Received another interrupt signal; immediately exiting.');
		process.exit(0);
	}
});
<commit_msg>Fixed carbon URL. Oh boy.<commit_after>#!/usr/bin/env node
'use babel';
'use strict';

import bot from './bot';
import config from './config';
import version from './version';
import * as db from './database';
import Character from './database/character';
import * as analytics from './util/analytics';
import DiceExpression from 'dice-expression-evaluator';

import ListCharactersCommand from './commands/characters/list';
import ViewCharacterCommand from './commands/characters/view';
import AddCharacterCommand from './commands/characters/add';
import DeleteCharacterCommand from './commands/characters/delete';
import ClearCharactersCommand from './commands/characters/clear';
import RollDiceCommand from './commands/dice/roll';
import MaxRollCommand from './commands/dice/max';
import MinRollCommand from './commands/dice/min';

bot.logger.info(`RPBot v${version} is starting...`);
analytics.sendEvent('Bot', 'started');

// Create bot
export const client = bot
	.registerDefaults()
	.registerModules([
		['characters', 'Characters'],
		['dice', 'Dice']
	])
	.registerCommands([
		ListCharactersCommand,
		ViewCharacterCommand,
		AddCharacterCommand,
		DeleteCharacterCommand,
		ClearCharactersCommand,
		RollDiceCommand,
		MaxRollCommand,
		MinRollCommand
	])
	.registerEvalObjects({
		db: db,
		Character: Character,
		config: config,
		version: version,
		dice: DiceExpression
	})
.createClient();

// Set up database
db.init().catch(err => {
	bot.logger.error(err);
	process.exit(1);
});

// Set up Carbonitex guild count updates
if(config.carbonUrl) {
	const request = require('request-promise-native');
	const sendCarbon = () => {
		request({
			method: 'POST',
			uri: config.carbonUrl,
			body: {
				key: config.carbonKey,
				servercount: client.guilds.size
			},
			json: true
		}).then(() => {
			bot.logger.info(`Sent guild count to Carbon with ${client.guilds.size} guilds.`);
		}).catch(err => {
			bot.logger.error('Error while sending guild count to Carbon.', err);
		});
	};
	client.once('ready', sendCarbon);
	client.on('guildCreate', sendCarbon);
	client.on('guildDelete', sendCarbon);
}

// Exit on interrupt
let interruptCount = 0;
process.on('SIGINT', async () => {
	interruptCount++;
	if(interruptCount === 1) {
		bot.logger.info('Received interrupt signal; closing database, destroying client, and exiting...');
		await Promise.all([
			db.close(),
			client.destroy()
		]).catch(err => {
			bot.logger.error(err);
		});
		process.exit(0);
	} else {
		bot.logger.info('Received another interrupt signal; immediately exiting.');
		process.exit(0);
	}
});
<|endoftext|>


<commit_before>// @flow
<commit_msg>:new: types for configuration and changes<commit_after>// @flow

export type Change = {
  name?: number,
  type: string,
  object: Object,
  index?: number,
  addedCount?: number,
  removed?: Array<any>
}

export type StoreConfig = {
  historyLimit?: number
}
<|endoftext|>


<commit_before>goog.provide('fontface.Ruler');

goog.require('dom');

goog.scope(function () {
  /**
   * @constructor
   * @param {string} text
   */
  fontface.Ruler = function (text) {
    var style = 'max-width:none;' +
                'display:inline-block;' +
                'position:absolute;' +
                'height:100%;' +
                'width:100%;' +
                'overflow:scroll;' +
                'font-size:16px;';

    this.element = dom.createElement('div');
    this.element.setAttribute('aria-hidden', 'true');

    dom.append(this.element, dom.createText(text));

    this.collapsible = dom.createElement('span');
    this.expandable = dom.createElement('span');
    this.collapsibleInner = dom.createElement('span');
    this.expandableInner = dom.createElement('span');

    this.lastOffsetWidth = -1;

    dom.style(this.collapsible, style);
    dom.style(this.expandable, style);
    dom.style(this.expandableInner, style);
    dom.style(this.collapsibleInner, 'display:inline-block;width:200%;height:200%;font-size:16px;max-width:none;');

    dom.append(this.collapsible, this.collapsibleInner);
    dom.append(this.expandable, this.expandableInner);

    dom.append(this.element, this.collapsible);
    dom.append(this.element, this.expandable);
  };

  var Ruler = fontface.Ruler;

  /**
   * @return {Element}
   */
  Ruler.prototype.getElement = function () {
    return this.element;
  };

  /**
   * @param {string} font
   */
  Ruler.prototype.setFont = function (font) {
    dom.style(this.element, 'max-width:none;' +
                            'min-width:20px;' +
                            'min-height:20px;' +
                            'display:inline-block;' +
                            'overflow:hidden;' +
                            'position:absolute;' +
                            'width:auto;' +
                            'margin:0;' +
                            'padding:0;' +
                            'top:-999px;' +
                            'left:-999px;' +
                            'white-space:nowrap;' +
                            'font:' + font + ';');
  };

  /**
   * @return {number}
   */
  Ruler.prototype.getWidth = function () {
    return this.element.offsetWidth;
  };

  /**
   * @param {string} width
   */
  Ruler.prototype.setWidth = function (width) {
    this.element.style.width = width + 'px';
  };

  /**
   * @private
   *
   * @return {boolean}
   */
  Ruler.prototype.reset = function () {
    var offsetWidth = this.getWidth(),
        width = offsetWidth + 100;

    this.expandableInner.style.width = width + 'px';
    this.expandable.scrollLeft = width;
    this.collapsible.scrollLeft = this.collapsible.scrollWidth + 100;

    if (this.lastOffsetWidth !== offsetWidth) {
      this.lastOffsetWidth = offsetWidth;
      return true;
    } else {
      return false;
    }
  };

  /**
   * @private
   * @param {function(number)} callback
   */
  Ruler.prototype.onScroll = function (callback) {
    if (this.reset() && this.element.parentNode !== null) {
      callback(this.lastOffsetWidth);
    }
  };

  /**
   * @param {function(number)} callback
   */
  Ruler.prototype.onResize = function (callback) {
    var that = this;

    function onScroll() {
      that.onScroll(callback);
    }

    dom.addListener(this.collapsible, 'scroll', onScroll);
    dom.addListener(this.expandable, 'scroll', onScroll);
    this.reset();
  };
});
<commit_msg>Add font-synthesis to the ruler to avoid faux styles (in browsers that support it.)<commit_after>goog.provide('fontface.Ruler');

goog.require('dom');

goog.scope(function () {
  /**
   * @constructor
   * @param {string} text
   */
  fontface.Ruler = function (text) {
    var style = 'max-width:none;' +
                'display:inline-block;' +
                'position:absolute;' +
                'height:100%;' +
                'width:100%;' +
                'overflow:scroll;' +
                'font-size:16px;';

    this.element = dom.createElement('div');
    this.element.setAttribute('aria-hidden', 'true');

    dom.append(this.element, dom.createText(text));

    this.collapsible = dom.createElement('span');
    this.expandable = dom.createElement('span');
    this.collapsibleInner = dom.createElement('span');
    this.expandableInner = dom.createElement('span');

    this.lastOffsetWidth = -1;

    dom.style(this.collapsible, style);
    dom.style(this.expandable, style);
    dom.style(this.expandableInner, style);
    dom.style(this.collapsibleInner, 'display:inline-block;width:200%;height:200%;font-size:16px;max-width:none;');

    dom.append(this.collapsible, this.collapsibleInner);
    dom.append(this.expandable, this.expandableInner);

    dom.append(this.element, this.collapsible);
    dom.append(this.element, this.expandable);
  };

  var Ruler = fontface.Ruler;

  /**
   * @return {Element}
   */
  Ruler.prototype.getElement = function () {
    return this.element;
  };

  /**
   * @param {string} font
   */
  Ruler.prototype.setFont = function (font) {
    dom.style(this.element, 'max-width:none;' +
                            'min-width:20px;' +
                            'min-height:20px;' +
                            'display:inline-block;' +
                            'overflow:hidden;' +
                            'position:absolute;' +
                            'width:auto;' +
                            'margin:0;' +
                            'padding:0;' +
                            'top:-999px;' +
                            'left:-999px;' +
                            'white-space:nowrap;' +
                            'font-synthesis:none;' +
                            'font:' + font + ';');
  };

  /**
   * @return {number}
   */
  Ruler.prototype.getWidth = function () {
    return this.element.offsetWidth;
  };

  /**
   * @param {string} width
   */
  Ruler.prototype.setWidth = function (width) {
    this.element.style.width = width + 'px';
  };

  /**
   * @private
   *
   * @return {boolean}
   */
  Ruler.prototype.reset = function () {
    var offsetWidth = this.getWidth(),
        width = offsetWidth + 100;

    this.expandableInner.style.width = width + 'px';
    this.expandable.scrollLeft = width;
    this.collapsible.scrollLeft = this.collapsible.scrollWidth + 100;

    if (this.lastOffsetWidth !== offsetWidth) {
      this.lastOffsetWidth = offsetWidth;
      return true;
    } else {
      return false;
    }
  };

  /**
   * @private
   * @param {function(number)} callback
   */
  Ruler.prototype.onScroll = function (callback) {
    if (this.reset() && this.element.parentNode !== null) {
      callback(this.lastOffsetWidth);
    }
  };

  /**
   * @param {function(number)} callback
   */
  Ruler.prototype.onResize = function (callback) {
    var that = this;

    function onScroll() {
      that.onScroll(callback);
    }

    dom.addListener(this.collapsible, 'scroll', onScroll);
    dom.addListener(this.expandable, 'scroll', onScroll);
    this.reset();
  };
});
<|endoftext|>


<commit_before>// Data types used in the OpenType font file.
// All OpenType fonts use Motorola-style byte ordering (Big Endian)

'use strict';

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

var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31

var decode = {};
var encode = {};
var sizeOf = {};

// Return a function that always returns the same value.
function constant(v) {
    return function () {
        return v;
    };
}

// OpenType data types //////////////////////////////////////////////////////

// Convert an 8-bit unsigned integer to a list of 1 byte.
encode.BYTE = function (v) {
    check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
    return [v];
};

sizeOf.BYTE = constant(1);

// Convert a 8-bit signed integer to a list of 1 byte.
encode.CHAR = function (v) {
    return [v.charCodeAt(0)];
};

sizeOf.BYTE = constant(1);

// Convert an ASCII string to a list of bytes.
encode.CHARARRAY = function (v) {
    var b = [];
    for (var i = 0; i < v.length; i += 1) {
        b.push(v.charCodeAt(i));
    }
    return b;
};

sizeOf.CHARARRAY = function (v) {
    return v.length;
};

// Convert a 16-bit unsigned integer to a list of 2 bytes.
encode.USHORT = function (v) {
    return [(v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.USHORT = constant(2);

// Convert a 16-bit signed integer to a list of 2 bytes.
encode.SHORT = function (v) {
    // Two's complement
    if (v >= LIMIT16){
        v = - ( 2 * LIMIT16 - v);
    }
    return [(v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.SHORT = constant(2);

// Convert a 24-bit unsigned integer to a list of 3 bytes.
encode.UINT24 = function (v) {
    return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.UINT24 = constant(3);

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.ULONG = function (v) {
    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.ULONG = constant(4);

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.LONG = function (v) {
     // Two's complement
    if (v >= LIMIT32){
        v = - ( 2 * LIMIT32 - v);
    }
    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.LONG = constant(4);

encode.FIXED = encode.ULONG;
sizeOf.FIXED = sizeOf.ULONG;

encode.FWORD = encode.SHORT;
sizeOf.FWORD = sizeOf.SHORT;

encode.UFWORD = encode.USHORT;
sizeOf.UFWORD = sizeOf.USHORT;

// FIXME Implement LONGDATETIME
encode.LONGDATETIME = function () {
    return [0, 0, 0, 0, 0, 0, 0, 0];
};

sizeOf.LONGDATETIME = constant(8);

// Convert a 4-char tag to a list of 4 bytes.
encode.TAG = function (v) {
    check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
    return [v.charCodeAt(0),
            v.charCodeAt(1),
            v.charCodeAt(2),
            v.charCodeAt(3)];
};

sizeOf.TAG = constant(4);

// CFF data types ///////////////////////////////////////////////////////////

encode.Card8 = encode.BYTE;
sizeOf.Card8 = sizeOf.BYTE;

encode.Card16 = encode.USHORT;
sizeOf.Card16 = sizeOf.USHORT;

encode.OffSize = encode.BYTE;
sizeOf.OffSize = sizeOf.BYTE;

encode.SID = encode.USHORT;
sizeOf.SID = sizeOf.USHORT;

// Convert a numeric operand or charstring number to a variable-size list of bytes.
encode.NUMBER = function (v) {
    var v2, b0, b1;
    if (v >= -107 && v <= 107) {
        return [v + 139];
    } else if (v >= 108 && v <= 1131 ) {
        v2 = v - 108;
        b0 = (v2 >> 8) & 0xFF;
        b1 = v2 - (b0 << 8);
        return [b0 + 247, b1];
    } else if (v >= -1131 && v <= -108) {
        v2 = -v - 108;
        b0 = (v2 >> 8) & 0xFF;
        b1 = v2 - (b0 << 8);
        return [b0 + 251, b1];
    } else if (v >= -32768 && v <= 32767) {
        return encode.NUMBER16(v);
    } else {
        return encode.NUMBER32(v);
    }
};

sizeOf.NUMBER = function (v) {
    return encode.NUMBER(v).length;
};

// Convert a signed number between -32768 and +32767 to a three-byte value.
// This ensures we always use three bytes, but is not the most compact format.
encode.NUMBER16 = function (v) {
    return [28, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.NUMBER16 = constant(2);

// Convert a signed number between -(2^31) and +(2^31-1) to a four-byte value.
// This is useful if you want to be sure you always use four bytes,
// at the expense of wasting a few bytes for smaller numbers.
encode.NUMBER32 = function (v) {
    return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.NUMBER32 = constant(4);

encode.NAME = encode.CHARARRAY;
sizeOf.NAME = sizeOf.CHARARRAY;

encode.STRING = encode.CHARARRAY;
sizeOf.STRING = sizeOf.CHARARRAY;

// Convert a ASCII string to a list of UTF16 bytes.
encode.UTF16 = function (v) {
    var b = [];
    for (var i = 0; i < v.length; i += 1) {
        b.push(0);
        b.push(v.charCodeAt(i));
    }
    return b;
};

sizeOf.UTF16 = function (v) {
    return v.length * 2;
};

// Convert a list of values to a CFF INDEX structure.
// The values should be objects containing name / type / value.
encode.INDEX = function (l) {
    var offSize, offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
        dataSize, i, v;
    // Because we have to know which data type to use to encode the offsets,
    // we have to go through the values twice: once to encode the data and
    // calculate the offets, then again to encode the offsets using the fitting data type.
    offset = 1; // First offset is always 1.
    offsets = [offset];
    data = [];
    dataSize = 0;
    for (i = 0; i < l.length; i += 1) {
        v = encode.OBJECT(l[i]);
        Array.prototype.push.apply(data, v);
        dataSize += v.length;
        offset += v.length;
        offsets.push(offset);
    }

    if (data.length === 0) {
        return [0, 0];
    }

    encodedOffsets = [];
    offSize = (1 + Math.floor(Math.log(dataSize)/Math.log(2)) / 8) | 0;
    offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
    for (i = 0; i < offsets.length; i += 1) {
        encodedOffset = offsetEncoder(offsets[i]);
        Array.prototype.push.apply(encodedOffsets, encodedOffset);
    }
    return Array.prototype.concat(encode.Card16(l.length),
                           encode.OffSize(offSize),
                           encodedOffsets,
                           data);
};

sizeOf.INDEX = function (v) {
    return encode.INDEX(v).length;
};

// Convert an object to a CFF DICT structure.
// The keys should be numeric.
// The values should be objects containing name / type / value.
encode.DICT = function (m) {
    var d = [];
    var keys = Object.keys(m);
    for (var i = 0; i < keys.length; i += 1) {
        // Object.keys() return string keys, but our keys are always numeric.
        var k = parseInt(keys[i], 0);
        var v = m[k];
        // Value comes before the key.
        d = d.concat(encode.OPERAND(v.value, v.type));
        d = d.concat(encode.OPERATOR(k));
    }
    return d;
};

sizeOf.DICT = function (m) {
    return encode.DICT(m).length;
};

encode.OPERATOR = function (v) {
    if (v < 1200) {
        return [v];
    } else {
        return [12, v - 1200];
    }
};

encode.OPERAND = function (v, type) {
    var d, i;
    d = [];
    if (Array.isArray(type)) {
        for (i = 0; i < type.length; i += 1) {
            check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
            d = d.concat(encode.OPERAND(v[i], type[i]));
        }
    } else {
        if (type === 'SID') {
            d = d.concat(encode.NUMBER(v));
        } else if (type === 'offset') {
            // We make it easy for ourselves and always encode offsets as
            // 4 bytes. This makes offset calculation for the top dict easier.
            d = d.concat(encode.NUMBER32(v));
        } else {
            // FIXME Add support for booleans
            d = d.concat(encode.NUMBER(v));
        }
    }
    return d;
};

encode.OP = encode.BYTE;
sizeOf.OP = sizeOf.BYTE;

// Convert a list of CharString operations to bytes.
encode.CHARSTRING = function (ops) {
    var d = [], i;
    for (i = 0; i < ops.length; i += 1) {
        var op = ops[i];
        var encodingFunction = encode[op.type];
        d = d.concat(encodingFunction(op.value));
    }
    return d;
};

sizeOf.CHARSTRING = function (ops) {
    return encode.CHARSTRING(ops).length;
};

// Utility functions ////////////////////////////////////////////////////////

// Convert an object containing name / type / value to bytes.
encode.OBJECT = function (v) {
    var encodingFunction = encode[v.type];
    check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
    return encodingFunction(v.value);
};

// Convert a table object to bytes.
// A table contains a list of fields containing the metadata (name, type and default value).
// The table itself has the field values set as attributes.
encode.TABLE = function (table) {
    var d = [];
    for (var i = 0; i < table.fields.length; i += 1) {
        var field = table.fields[i];
        var encodingFunction = encode[field.type];
        check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type);
        var value = table[field.name];
        if (value === undefined) {
            value = field.value;
        }
        var bytes = encodingFunction(value);
        d = d.concat(bytes);
    }
    return d;
};

// Merge in a list of bytes.
encode.LITERAL = function (v) {
    return v;
};

sizeOf.LITERAL = function (v) {
    return v.length;
};

exports.decode = decode;
exports.encode = encode;
exports.sizeOf = sizeOf;
<commit_msg>Compacter implementation of NUMBER encoder.<commit_after>// Data types used in the OpenType font file.
// All OpenType fonts use Motorola-style byte ordering (Big Endian)

'use strict';

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

var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31

var decode = {};
var encode = {};
var sizeOf = {};

// Return a function that always returns the same value.
function constant(v) {
    return function () {
        return v;
    };
}

// OpenType data types //////////////////////////////////////////////////////

// Convert an 8-bit unsigned integer to a list of 1 byte.
encode.BYTE = function (v) {
    check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
    return [v];
};

sizeOf.BYTE = constant(1);

// Convert a 8-bit signed integer to a list of 1 byte.
encode.CHAR = function (v) {
    return [v.charCodeAt(0)];
};

sizeOf.BYTE = constant(1);

// Convert an ASCII string to a list of bytes.
encode.CHARARRAY = function (v) {
    var b = [];
    for (var i = 0; i < v.length; i += 1) {
        b.push(v.charCodeAt(i));
    }
    return b;
};

sizeOf.CHARARRAY = function (v) {
    return v.length;
};

// Convert a 16-bit unsigned integer to a list of 2 bytes.
encode.USHORT = function (v) {
    return [(v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.USHORT = constant(2);

// Convert a 16-bit signed integer to a list of 2 bytes.
encode.SHORT = function (v) {
    // Two's complement
    if (v >= LIMIT16){
        v = - ( 2 * LIMIT16 - v);
    }
    return [(v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.SHORT = constant(2);

// Convert a 24-bit unsigned integer to a list of 3 bytes.
encode.UINT24 = function (v) {
    return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.UINT24 = constant(3);

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.ULONG = function (v) {
    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.ULONG = constant(4);

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.LONG = function (v) {
     // Two's complement
    if (v >= LIMIT32){
        v = - ( 2 * LIMIT32 - v);
    }
    return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.LONG = constant(4);

encode.FIXED = encode.ULONG;
sizeOf.FIXED = sizeOf.ULONG;

encode.FWORD = encode.SHORT;
sizeOf.FWORD = sizeOf.SHORT;

encode.UFWORD = encode.USHORT;
sizeOf.UFWORD = sizeOf.USHORT;

// FIXME Implement LONGDATETIME
encode.LONGDATETIME = function () {
    return [0, 0, 0, 0, 0, 0, 0, 0];
};

sizeOf.LONGDATETIME = constant(8);

// Convert a 4-char tag to a list of 4 bytes.
encode.TAG = function (v) {
    check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
    return [v.charCodeAt(0),
            v.charCodeAt(1),
            v.charCodeAt(2),
            v.charCodeAt(3)];
};

sizeOf.TAG = constant(4);

// CFF data types ///////////////////////////////////////////////////////////

encode.Card8 = encode.BYTE;
sizeOf.Card8 = sizeOf.BYTE;

encode.Card16 = encode.USHORT;
sizeOf.Card16 = sizeOf.USHORT;

encode.OffSize = encode.BYTE;
sizeOf.OffSize = sizeOf.BYTE;

encode.SID = encode.USHORT;
sizeOf.SID = sizeOf.USHORT;

// Convert a numeric operand or charstring number to a variable-size list of bytes.
encode.NUMBER = function (v) {
    if (v >= -107 && v <= 107) {
        return [v + 139];
    } else if (v >= 108 && v <= 1131 ) {
        v = v - 108;
        return [(v >> 8) + 247, v & 0xFF];
    } else if (v >= -1131 && v <= -108) {
        v = -v - 108;
        return [(v >> 8) + 251, v & 0xFF];
    } else if (v >= -32768 && v <= 32767) {
        return encode.NUMBER16(v);
    } else {
        return encode.NUMBER32(v);
    }
};

sizeOf.NUMBER = function (v) {
    return encode.NUMBER(v).length;
};

// Convert a signed number between -32768 and +32767 to a three-byte value.
// This ensures we always use three bytes, but is not the most compact format.
encode.NUMBER16 = function (v) {
    return [28, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.NUMBER16 = constant(2);

// Convert a signed number between -(2^31) and +(2^31-1) to a four-byte value.
// This is useful if you want to be sure you always use four bytes,
// at the expense of wasting a few bytes for smaller numbers.
encode.NUMBER32 = function (v) {
    return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
};

sizeOf.NUMBER32 = constant(4);

encode.NAME = encode.CHARARRAY;
sizeOf.NAME = sizeOf.CHARARRAY;

encode.STRING = encode.CHARARRAY;
sizeOf.STRING = sizeOf.CHARARRAY;

// Convert a ASCII string to a list of UTF16 bytes.
encode.UTF16 = function (v) {
    var b = [];
    for (var i = 0; i < v.length; i += 1) {
        b.push(0);
        b.push(v.charCodeAt(i));
    }
    return b;
};

sizeOf.UTF16 = function (v) {
    return v.length * 2;
};

// Convert a list of values to a CFF INDEX structure.
// The values should be objects containing name / type / value.
encode.INDEX = function (l) {
    var offSize, offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
        dataSize, i, v;
    // Because we have to know which data type to use to encode the offsets,
    // we have to go through the values twice: once to encode the data and
    // calculate the offets, then again to encode the offsets using the fitting data type.
    offset = 1; // First offset is always 1.
    offsets = [offset];
    data = [];
    dataSize = 0;
    for (i = 0; i < l.length; i += 1) {
        v = encode.OBJECT(l[i]);
        Array.prototype.push.apply(data, v);
        dataSize += v.length;
        offset += v.length;
        offsets.push(offset);
    }

    if (data.length === 0) {
        return [0, 0];
    }

    encodedOffsets = [];
    offSize = (1 + Math.floor(Math.log(dataSize)/Math.log(2)) / 8) | 0;
    offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
    for (i = 0; i < offsets.length; i += 1) {
        encodedOffset = offsetEncoder(offsets[i]);
        Array.prototype.push.apply(encodedOffsets, encodedOffset);
    }
    return Array.prototype.concat(encode.Card16(l.length),
                           encode.OffSize(offSize),
                           encodedOffsets,
                           data);
};

sizeOf.INDEX = function (v) {
    return encode.INDEX(v).length;
};

// Convert an object to a CFF DICT structure.
// The keys should be numeric.
// The values should be objects containing name / type / value.
encode.DICT = function (m) {
    var d = [];
    var keys = Object.keys(m);
    for (var i = 0; i < keys.length; i += 1) {
        // Object.keys() return string keys, but our keys are always numeric.
        var k = parseInt(keys[i], 0);
        var v = m[k];
        // Value comes before the key.
        d = d.concat(encode.OPERAND(v.value, v.type));
        d = d.concat(encode.OPERATOR(k));
    }
    return d;
};

sizeOf.DICT = function (m) {
    return encode.DICT(m).length;
};

encode.OPERATOR = function (v) {
    if (v < 1200) {
        return [v];
    } else {
        return [12, v - 1200];
    }
};

encode.OPERAND = function (v, type) {
    var d, i;
    d = [];
    if (Array.isArray(type)) {
        for (i = 0; i < type.length; i += 1) {
            check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
            d = d.concat(encode.OPERAND(v[i], type[i]));
        }
    } else {
        if (type === 'SID') {
            d = d.concat(encode.NUMBER(v));
        } else if (type === 'offset') {
            // We make it easy for ourselves and always encode offsets as
            // 4 bytes. This makes offset calculation for the top dict easier.
            d = d.concat(encode.NUMBER32(v));
        } else {
            // FIXME Add support for booleans
            d = d.concat(encode.NUMBER(v));
        }
    }
    return d;
};

encode.OP = encode.BYTE;
sizeOf.OP = sizeOf.BYTE;

// Convert a list of CharString operations to bytes.
encode.CHARSTRING = function (ops) {
    var d = [], i;
    for (i = 0; i < ops.length; i += 1) {
        var op = ops[i];
        var encodingFunction = encode[op.type];
        d = d.concat(encodingFunction(op.value));
    }
    return d;
};

sizeOf.CHARSTRING = function (ops) {
    return encode.CHARSTRING(ops).length;
};

// Utility functions ////////////////////////////////////////////////////////

// Convert an object containing name / type / value to bytes.
encode.OBJECT = function (v) {
    var encodingFunction = encode[v.type];
    check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
    return encodingFunction(v.value);
};

// Convert a table object to bytes.
// A table contains a list of fields containing the metadata (name, type and default value).
// The table itself has the field values set as attributes.
encode.TABLE = function (table) {
    var d = [];
    for (var i = 0; i < table.fields.length; i += 1) {
        var field = table.fields[i];
        var encodingFunction = encode[field.type];
        check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type);
        var value = table[field.name];
        if (value === undefined) {
            value = field.value;
        }
        var bytes = encodingFunction(value);
        d = d.concat(bytes);
    }
    return d;
};

// Merge in a list of bytes.
encode.LITERAL = function (v) {
    return v;
};

sizeOf.LITERAL = function (v) {
    return v.length;
};

exports.decode = decode;
exports.encode = encode;
exports.sizeOf = sizeOf;
<|endoftext|>


<commit_before>var rules = function() {

  var _rules = [];

  //Public Methods *************************************************************
  var getRuleByRuleClass = function(ruleClasses) {

    var isArray = Array.isArray(ruleClasses);
    var rule = null;

    for (var i = 0; i < _rules.length; i++) {

      var ruleDoesNotMatch = isArray ? ruleClasses.indexOf(_rules[i].ruleClass) === -1 : _rules[i].ruleClass !== ruleClasses;
      if (ruleDoesNotMatch) continue;

      rule = _rules[i];
      break;
    }
    return rule;
  };

  var addValidationRule = function(ruleTypeOrRules, ruleClass, validationFunction, errorMessageParam) {

    var isArray = Array.isArray(ruleTypeOrRules);
    var isRule = typeof ruleTypeOrRules === 'object' && !isArray;

    if (isArray || isRule) {

      if (isRule) ruleTypeOrRules = [ruleTypeOrRules];

      ruleTypeOrRules.forEach(function(rule) {
        _upsertValidationRule(rule.ruleType, rule.ruleClass, rule.validationFunction, rule.errorMessage);
      });

    } else {
      _upsertValidationRule(ruleTypeOrRules, ruleClass, validationFunction, errorMessageParam);
    }
  };

  //Private Methods ************************************************************
  var _Rule = function(ruleType, ruleClass, validationFunction, errorMessageFunction) {
    this.ruleType = ruleType;
    this.ruleClass = ruleClass;
    this.validate = validationFunction;
    this.getErrorMessage = errorMessageFunction;
  };

  var _upsertValidationRule = function(ruleType, ruleClass, validationFunction, errorMessageParam) {

    if (ruleType !== 'alpha' && ruleType !== 'numeric')
      throw new Error('The rule type for a new validation rule must be either "alpha" or "numeric"');

    if (typeof ruleClass !== 'string')
      throw new Error('The rule class for a new validation rule is missing or is not of type string');

    if (typeof validationFunction !== 'function')
      throw new Error('The validation function for a new validation rule is missing or is not of type function');

    if (errorMessageParam === undefined)
      errorMessageParam = new Function('', 'return "Invalid value";');

    if (typeof errorMessageParam === 'string')
      errorMessageParam = new Function('', 'return "' + errorMessageParam + '";');

    //Remove exsiting rule if found
    var rule = getRuleByRuleClass(ruleClass);
    if (rule !== null) {
      var ruleIndex = _rules.indexOf(rule);
      _rules.splice(ruleIndex, 1);
    }

    _rules.push(new _Rule(ruleType, ruleClass, validationFunction, errorMessageParam));

  };

  var _validateAlphaOnly = function(element) {

    var value = element.value;
    var noSpace = element.hasAttribute('data-no-space');

    /*
     * Any case insensitive Roman character with periods, dashes, and spaces (if allowed).
     *
     * e.g. cool | cool-beans | cool beans | beans.
     */
    var alphaOnlyRegexString = '^([A-Za-z@\.\-])+$';
    var alphaOnlyRegex = new RegExp(alphaOnlyRegexString.replace(/@/g, noSpace ? '' : '\\s'));

    return alphaOnlyRegex.test(value);
  };

  var _validateAlphaZip = function(element) {
    /*
     * Matches all Canadian or American postal codes with different formats. For USA it is:
     * any 5 digits followed optionally by an optional space or dash or empty string and any 4 digits after the optional
     * space or dash. For Canada it is: certain capital letters (only one), any digit (only one), any capital letter (only one),
     * optional space, any digit (only one), any capitol letter (only one), and and digit (only one).
     *
     * e.g. 19608 | 19608-8911 | A9C1A1 | A9C 1A1
     *
     */
    return /(^\d{5}([\s-]?\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} ?\d{1}[A-Z]{1}\d{1}$)/.test(element.value);
  };

  var _validateAlphaNumeric = function(element) {

    var value = element.value;
    var noSpace = element.hasAttribute('data-no-space');

    /*
     * Any case insensitive Roman character, digit, and spaces (if allowed)
     *
     * e.g. Cool | C00l
     */
    var alphaNumericRegexString = '^([a-zA-Z0-9@]+)$';
    var alphaNumericRegex = new RegExp(alphaNumericRegexString.replace(/@/g, noSpace ? '' : '\\s'));

    return alphaNumericRegex.test(value);
  };

  var _validateAlphaEmail = function(element) {
    /*
     * One or more non space charater + literal '@', + One or more non space charater + literal '.' + One or more non space charater.
     * It does not check tld and special chacter validity.
     *
     * e.g. a@a.a | bob@google.com | cool-beans@beans.com.uk | $#%@$%@$.com
     */
    return /^(\S+@\S+\.\S+)$/.test(element.value);
  };

  var _validateNumericWhole = function(element) {

    var value = element.value;
    var noThousandsSeparator = element.hasAttribute('data-no-thousands-separator');
    /*
     *  A negative or non negative number with optional thousands commas
     *
     *  e.g. 54 | -54 | -54,000 | 54000
     */
    var validNumericWhole = /^-?(([\d]{1,3}(,{1}[\d]{3})*)|[\d]+)$/.test(value);
    if (noThousandsSeparator) validNumericWhole = validNumericWhole && value.indexOf(',') === -1;

    return validNumericWhole;

  };

  var _getNumericWholeErrorMessage = function(element) {

    var errorMessage = 'Enter a whole number';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  var _validateNumericDecimalString = function(element) {

    var value = element.value;
    var noThousandsSeparator = element.hasAttribute('data-no-thousands-separator');
    var decimalMax = element.getAttribute('data-decimal-max');
    if (decimalMax === null) decimalMax = 2;

    /*
     * A negative or non negative monetary amount with optional thousands commas and optional hundreds decimal place
     *
     * e.g. -54 | 54 | 54.00 | -54,544 | 54,544.54
     */
    var numericDecimalRegexString = '^-?((([\\d]{1,3}(,[\\d]{3})*)+(\\.[\\d]{1,decimalPlaces})?)|[\\d]+(\\.[\\d]{1,decimalPlaces})?)$';
    var numericDecimalRegex = new RegExp(numericDecimalRegexString.replace(/decimalPlaces/g, decimalMax));

    var validNumericDecimal = numericDecimalRegex.test(value);
    if (noThousandsSeparator) validNumericDecimal = validNumericDecimal && value.indexOf(',') === -1;

    return validNumericDecimal;
  };
  var _getNumericDecimalErrorMessage = function(element) {

    var errorMessage = 'Please enter a number';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    var maxDecimals = element.hasAttribute('data-decimal-max') ? element.getAttribute('data-decimal-max') : 2;
    errorMessage += ' with ' + maxDecimals + ' decimal places max';

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' and from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' and greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' and lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  /**
   * @deprecated Since v1.3.0. Use numeric-whole instead and specify a min/max on the element
   */
  var _validateNumericFullYear = function(element) {
    /*
       * A four digit number
       *
       * e.g. 1999 | 2010 | 0000
       */
    // eslint-disable-next-line no-console
    console.warn(
      'numeric-full-year has been deprecated since v1.3.0. Use numeric-whole instead and specify a min/max on the element'
    );
    return /^(\d{4})$/.test(element.value);
  };

  var _getNumericFullYearErrorMessage = function(element) {

    var errorMessage = 'Please enter a 4 digit year';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  var _validateNumericJqueryDatePicker = function(element) {

    var $element = $(element);
    var isValid = $element.datepicker('getDate') !== null;

    return isValid;
  };

  //Add default rules
  _upsertValidationRule('alpha', 'alpha-only', _validateAlphaOnly, 'Only letters, spaces, hypens, and periods are allowed');
  _upsertValidationRule('alpha', 'alpha-zip', _validateAlphaZip, 'Enter a valid zip code');
  _upsertValidationRule('alpha', 'alpha-numeric', _validateAlphaNumeric, 'Enter only alphanumeric characters');
  _upsertValidationRule('alpha', 'alpha-email', _validateAlphaEmail, 'Make sure the email is correct');

  _upsertValidationRule('numeric', 'numeric-whole', _validateNumericWhole, _getNumericWholeErrorMessage);
  _upsertValidationRule('numeric', 'numeric-decimal', _validateNumericDecimalString, _getNumericDecimalErrorMessage);
  _upsertValidationRule('numeric', 'numeric-full-year', _validateNumericFullYear, _getNumericFullYearErrorMessage);
  _upsertValidationRule('numeric', 'numeric-jquery-date', _validateNumericJqueryDatePicker, 'Please select a date from the date picker');

  return {
    getRuleByRuleClass: getRuleByRuleClass,
    addValidationRule: addValidationRule
  };

};

module.exports = function() {return rules();};
<commit_msg>Remove unnecessary escape character<commit_after>var rules = function() {

  var _rules = [];

  //Public Methods *************************************************************
  var getRuleByRuleClass = function(ruleClasses) {

    var isArray = Array.isArray(ruleClasses);
    var rule = null;

    for (var i = 0; i < _rules.length; i++) {

      var ruleDoesNotMatch = isArray ? ruleClasses.indexOf(_rules[i].ruleClass) === -1 : _rules[i].ruleClass !== ruleClasses;
      if (ruleDoesNotMatch) continue;

      rule = _rules[i];
      break;
    }
    return rule;
  };

  var addValidationRule = function(ruleTypeOrRules, ruleClass, validationFunction, errorMessageParam) {

    var isArray = Array.isArray(ruleTypeOrRules);
    var isRule = typeof ruleTypeOrRules === 'object' && !isArray;

    if (isArray || isRule) {

      if (isRule) ruleTypeOrRules = [ruleTypeOrRules];

      ruleTypeOrRules.forEach(function(rule) {
        _upsertValidationRule(rule.ruleType, rule.ruleClass, rule.validationFunction, rule.errorMessage);
      });

    } else {
      _upsertValidationRule(ruleTypeOrRules, ruleClass, validationFunction, errorMessageParam);
    }
  };

  //Private Methods ************************************************************
  var _Rule = function(ruleType, ruleClass, validationFunction, errorMessageFunction) {
    this.ruleType = ruleType;
    this.ruleClass = ruleClass;
    this.validate = validationFunction;
    this.getErrorMessage = errorMessageFunction;
  };

  var _upsertValidationRule = function(ruleType, ruleClass, validationFunction, errorMessageParam) {

    if (ruleType !== 'alpha' && ruleType !== 'numeric')
      throw new Error('The rule type for a new validation rule must be either "alpha" or "numeric"');

    if (typeof ruleClass !== 'string')
      throw new Error('The rule class for a new validation rule is missing or is not of type string');

    if (typeof validationFunction !== 'function')
      throw new Error('The validation function for a new validation rule is missing or is not of type function');

    if (errorMessageParam === undefined)
      errorMessageParam = new Function('', 'return "Invalid value";');

    if (typeof errorMessageParam === 'string')
      errorMessageParam = new Function('', 'return "' + errorMessageParam + '";');

    //Remove exsiting rule if found
    var rule = getRuleByRuleClass(ruleClass);
    if (rule !== null) {
      var ruleIndex = _rules.indexOf(rule);
      _rules.splice(ruleIndex, 1);
    }

    _rules.push(new _Rule(ruleType, ruleClass, validationFunction, errorMessageParam));

  };

  var _validateAlphaOnly = function(element) {

    var value = element.value;
    var noSpace = element.hasAttribute('data-no-space');

    /*
     * Any case insensitive Roman character with periods, dashes, and spaces (if allowed).
     *
     * e.g. cool | cool-beans | cool beans | beans.
     */
    var alphaOnlyRegexString = '^([A-Za-z@.-])+$';
    var alphaOnlyRegex = new RegExp(alphaOnlyRegexString.replace(/@/g, noSpace ? '' : '\\s'));

    return alphaOnlyRegex.test(value);
  };

  var _validateAlphaZip = function(element) {
    /*
     * Matches all Canadian or American postal codes with different formats. For USA it is:
     * any 5 digits followed optionally by an optional space or dash or empty string and any 4 digits after the optional
     * space or dash. For Canada it is: certain capital letters (only one), any digit (only one), any capital letter (only one),
     * optional space, any digit (only one), any capitol letter (only one), and and digit (only one).
     *
     * e.g. 19608 | 19608-8911 | A9C1A1 | A9C 1A1
     *
     */
    return /(^\d{5}([\s-]?\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} ?\d{1}[A-Z]{1}\d{1}$)/.test(element.value);
  };

  var _validateAlphaNumeric = function(element) {

    var value = element.value;
    var noSpace = element.hasAttribute('data-no-space');

    /*
     * Any case insensitive Roman character, digit, and spaces (if allowed)
     *
     * e.g. Cool | C00l
     */
    var alphaNumericRegexString = '^([a-zA-Z0-9@]+)$';
    var alphaNumericRegex = new RegExp(alphaNumericRegexString.replace(/@/g, noSpace ? '' : '\\s'));

    return alphaNumericRegex.test(value);
  };

  var _validateAlphaEmail = function(element) {
    /*
     * One or more non space charater + literal '@', + One or more non space charater + literal '.' + One or more non space charater.
     * It does not check tld and special chacter validity.
     *
     * e.g. a@a.a | bob@google.com | cool-beans@beans.com.uk | $#%@$%@$.com
     */
    return /^(\S+@\S+\.\S+)$/.test(element.value);
  };

  var _validateNumericWhole = function(element) {

    var value = element.value;
    var noThousandsSeparator = element.hasAttribute('data-no-thousands-separator');
    /*
     *  A negative or non negative number with optional thousands commas
     *
     *  e.g. 54 | -54 | -54,000 | 54000
     */
    var validNumericWhole = /^-?(([\d]{1,3}(,{1}[\d]{3})*)|[\d]+)$/.test(value);
    if (noThousandsSeparator) validNumericWhole = validNumericWhole && value.indexOf(',') === -1;

    return validNumericWhole;

  };

  var _getNumericWholeErrorMessage = function(element) {

    var errorMessage = 'Enter a whole number';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  var _validateNumericDecimalString = function(element) {

    var value = element.value;
    var noThousandsSeparator = element.hasAttribute('data-no-thousands-separator');
    var decimalMax = element.getAttribute('data-decimal-max');
    if (decimalMax === null) decimalMax = 2;

    /*
     * A negative or non negative monetary amount with optional thousands commas and optional hundreds decimal place
     *
     * e.g. -54 | 54 | 54.00 | -54,544 | 54,544.54
     */
    var numericDecimalRegexString = '^-?((([\\d]{1,3}(,[\\d]{3})*)+(\\.[\\d]{1,decimalPlaces})?)|[\\d]+(\\.[\\d]{1,decimalPlaces})?)$';
    var numericDecimalRegex = new RegExp(numericDecimalRegexString.replace(/decimalPlaces/g, decimalMax));

    var validNumericDecimal = numericDecimalRegex.test(value);
    if (noThousandsSeparator) validNumericDecimal = validNumericDecimal && value.indexOf(',') === -1;

    return validNumericDecimal;
  };
  var _getNumericDecimalErrorMessage = function(element) {

    var errorMessage = 'Please enter a number';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    var maxDecimals = element.hasAttribute('data-decimal-max') ? element.getAttribute('data-decimal-max') : 2;
    errorMessage += ' with ' + maxDecimals + ' decimal places max';

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' and from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' and greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' and lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  /**
   * @deprecated Since v1.3.0. Use numeric-whole instead and specify a min/max on the element
   */
  var _validateNumericFullYear = function(element) {
    /*
       * A four digit number
       *
       * e.g. 1999 | 2010 | 0000
       */
    // eslint-disable-next-line no-console
    console.warn(
      'numeric-full-year has been deprecated since v1.3.0. Use numeric-whole instead and specify a min/max on the element'
    );
    return /^(\d{4})$/.test(element.value);
  };

  var _getNumericFullYearErrorMessage = function(element) {

    var errorMessage = 'Please enter a 4 digit year';

    var hasMinLimit = element.hasAttribute('min');
    var hasMaxLimit = element.hasAttribute('max');

    if (hasMinLimit && hasMaxLimit) {
      errorMessage = errorMessage + ' from ' + element.getAttribute('min') + ' to ' + element.getAttribute('max');
    } else if (hasMinLimit) {
      errorMessage = errorMessage + ' greater or equal to ' + element.getAttribute('min');
    } else if (hasMaxLimit) {
      errorMessage = errorMessage + ' lesser or equal to ' + element.getAttribute('max');
    }

    return errorMessage;
  };

  var _validateNumericJqueryDatePicker = function(element) {

    var $element = $(element);
    var isValid = $element.datepicker('getDate') !== null;

    return isValid;
  };

  //Add default rules
  _upsertValidationRule('alpha', 'alpha-only', _validateAlphaOnly, 'Only letters, spaces, hypens, and periods are allowed');
  _upsertValidationRule('alpha', 'alpha-zip', _validateAlphaZip, 'Enter a valid zip code');
  _upsertValidationRule('alpha', 'alpha-numeric', _validateAlphaNumeric, 'Enter only alphanumeric characters');
  _upsertValidationRule('alpha', 'alpha-email', _validateAlphaEmail, 'Make sure the email is correct');

  _upsertValidationRule('numeric', 'numeric-whole', _validateNumericWhole, _getNumericWholeErrorMessage);
  _upsertValidationRule('numeric', 'numeric-decimal', _validateNumericDecimalString, _getNumericDecimalErrorMessage);
  _upsertValidationRule('numeric', 'numeric-full-year', _validateNumericFullYear, _getNumericFullYearErrorMessage);
  _upsertValidationRule('numeric', 'numeric-jquery-date', _validateNumericJqueryDatePicker, 'Please select a date from the date picker');

  return {
    getRuleByRuleClass: getRuleByRuleClass,
    addValidationRule: addValidationRule
  };

};

module.exports = function() {return rules();};
<|endoftext|>


<commit_before>'use strict;';

var Uppik = function(target, options) {
    if (!(target instanceof HTMLElement)) {
        target = document.getElementById(target);
    }
    this.target = target;
    this.options = {
        showState: true,
        fakeFileInput: false,
        fileInputClass: '',
        fileInputStyle: '',
        onSuccess: this.onSuccess,
        onUpload: this.onUpload,
        onError: this.onError
    };
    if (options) {
        for (key in options) {
            this.options[key] = options[key];
        }
    }
    this.currentFile = null;
    this.tryTime = 0;
    this.token = '';
    this.endpoint = '';
    this.quality = 0.5;
    this.fadeoutMessageInterval = null;
    this.hideMessageInterval = null;
    this.msgContainer = null;
    this.msgBody = null;

    //multiple file upload
    this.currentFileIndex = 1;
    this.totalFile = 1;

    this.init();
}

Uppik.inquiryUrl = 'http://www.uppik.net/api/inquiry';
Uppik.maxSize = 1024;
Uppik.messageTTL = 5000;
Uppik.maxTry = 10;
Uppik.allowedMimes = ["image/gif", "image/jpeg", "image/png", "image/jpg",];

Uppik.parseJson = function(str) {
    var output = {};
    try {
        output = JSON.parse(str);
    } catch (ex) {
        //nothing
    }
    return output;
}

Uppik.prototype.init = function() {
    this.initMessage();
    if (!this.checkRequirement()) {
        this.disableUpload();
        return;
    }
    this.initElements();
    this.inquiry();
}

Uppik.prototype.initMessage = function() {
    //message container
    var msgContainer = document.createElement('div');
    msgContainer.style.position = 'fixed';
    msgContainer.style.top = 0;
    msgContainer.style.left = 0;
    msgContainer.style.width = '100%';
    msgContainer.style.display = 'none';
    msgContainer.style.textAlign = 'center';
    msgContainer.style.backgroundColor = 'transparent';
    msgContainer.style.transition = 'opacity 0.5s ease';
    this.msgContainer = msgContainer;

    //message body
    var msgBody = document.createElement('span');
    msgBody.style.display = 'inline-block';
    msgBody.style.padding = '0.5em 1.5em';
    msgBody.style.marginTop = '0.5em';
    msgBody.style.borderRadius = '1em';
    msgBody.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
    this.msgBody = msgBody;

    msgContainer.appendChild(msgBody);
    document.body.appendChild(msgContainer);
}

Uppik.prototype.initElements = function() {
    // file input element
    var input = document.createElement('input');
    input.type = 'file';
    input.className = this.options.fileInputClass;
    input.style = this.options.fileInputStyle;

    if (this.options.fakeFileInput) {
        this.target.style.position = 'relative';
        this.target.style.overflow = 'hidden';
        input.style.width = '1000px';
        input.style.height = '1000px';
        input.style.fontSize = '1000px';
        input.style.opacity = 0;
        input.style.position = 'absolute';
        input.style.left = '0px';
        input.style.top = '0px';
        input.style.cursor = 'pointer';
    }

    //attack file input to body
    this.target.appendChild(input);
    this.input = input;
    //bind events
    var me = this;
    input.onchange = function(e) {
        e.stopPropagation();
        me.onFileSelected(e);
    }
}

Uppik.prototype.disableUpload = function() {
    var me = this;
    this.target.onclick = function (e) {
        e.preventDefault();
        me.showMessage('This browser is not supported, lets switch to a modern browser.', true);
    }
}

Uppik.prototype.showMessage = function(msg, isError, keepShow) {
    if (this.fadeoutMessageInterval) {
        clearInterval(this.fadeoutMessageInterval);
        this.fadeoutMessageInterval = null;
    }
    if (this.hideMessageInterval) {
        clearInterval(this.hideMessageInterval);
        this.hideMessageInterval = null;
    }
    this.msgBody.innerText = msg;
    if (isError) {
        this.msgBody.style.color = '#ff0000';
    } else {
        this.msgBody.style.color = '#00ff00';
    }
    this.msgContainer.style.opacity = 1;
    this.msgContainer.style.display = 'block';
    var me = this;
    if (keepShow) {
        return;
    }
    this.hideMessageInterval = setInterval(function() {
        me.hideMessage();
    }, Uppik.messageTTL);
}

Uppik.prototype.hideMessage = function() {
    if (this.hideMessageInterval) {
        clearInterval(this.hideMessageInterval);
        this.hideMessageInterval = null;
    }
    this.msgContainer.style.opacity = 0;
    var me = this;
    this.fadeoutMessageInterval = setInterval(function() {
        me.msgContainer.style.display = 'none';
        if (me.fadeoutMessageInterval) {
            clearInterval(me.fadeoutMessageInterval);
            me.fadeoutMessageInterval = null;
        }
    }, 500);
}

Uppik.prototype._onSuccess = function(image) {
    this.input.value = null;
    this.input.removeAttribute('disabled');
    if (this.options.showState) {
        this.hideMessage();
    }
    this.options.onSuccess.apply(this, [image.url, image]);
}

Uppik.prototype._onUpload = function() {
    this.input.disabled = true;
    if (this.options.showState) {
        this.showMessage('Uploading...', false, true)
    }
    this.options.onUpload.apply(this, [this.currentFileIndex, this.totalFile]);
}

Uppik.prototype._onError = function(error) {
    this.input.value = null;
    this.input.removeAttribute('disabled');
    if (this.options.showState) {
        this.showMessage(error, true);
    }
    this.options.onError.apply(this, [error]);
}

Uppik.prototype.onFileSelected = function(event) {
    this.loadImage(event.target.files[0]);
}

Uppik.prototype.onSuccess = function(url, image) {
    console.log(image);
}

Uppik.prototype.onUpload = function(index, total) {
    console.log('Uploading...');
}

Uppik.prototype.onError = function(error) {
    console.log(error);
}

Uppik.prototype.inquiry = function() {
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('GET', Uppik.inquiryUrl, true);
        req.onreadystatechange = function() {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var data = Uppik.parseJson(req.responseText);
                    if (data.endpoint) {
                        me.endpoint = data.endpoint;
                        me.token = data.token;
                        me.quality = data.quality;
                        return;
                    }
                }
                me.showMessage('Cannot get information from server. Please try later.', true);
            }
        };
        req.send();
    }
}

Uppik.prototype.upload = function(data) {
    if (this.token == '' || this.enpoint == '') {
        return;
    }
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('POST', this.endpoint + '/upload', true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.onreadystatechange = function() {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var res = Uppik.parseJson(req.responseText);
                    if(res.image) {
                        //synchronous upload return url immediately
                        me._onSuccess(res.image);
                        return;
                    }
                    if (res.id) {
                        // asynchronous upload return file id
                        me.tryTime = 0;
                        me.currentFile = res.id;
                        me.delayQueryStatus();
                        return;
                    }
                }
                me._onError('Upload failed, please try again later.');
            }
        };
        this.hideMessage();
        req.send('token=' + this.token + '&data=' + encodeURI(data));
        this._onUpload();
    }
}

Uppik.prototype.checkRequirement = function() {
    if (typeof window.URL === 'undefined') {
        return false;
    }
    return true;
}

Uppik.prototype.queryStatus = function() {
    if (this.token == '' || this.endpoint == '') {
        return;
    }
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('GET', this.endpoint + '/status?id=' + this.currentFile + '&token=' + this.token, true);
        req.onreadystatechange = function () {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var res = Uppik.parseJson(req.responseText);
                    if (res.status == 'success') {
                        me._onSuccess(res.image);
                        return;
                    }
                    if (res.status == 'failed') {
                        me.showMessage(res.error, true);
                        return;
                    }
                }
                //error or pending
                me.tryTime++;
                if (me.tryTime < Uppik.maxTry) {
                    me.delayQueryStatus();
                } else {
                    me._onError('Upload timeout, please try again.');
                }
            }
        }
        req.send();
    }
}

Uppik.prototype.delayQueryStatus = function() {
    var me = this;
    setTimeout(function() {
        me.queryStatus()
    }, 1000);
}

Uppik.prototype.loadImage = function(file) {
    var url = URL.createObjectURL(file);
    var img = new Image();
    var me = this;
    if (Uppik.allowedMimes.indexOf(file.type) == -1) {
        return;
    }
    img.onload = function() {
        URL.revokeObjectURL(url);
        var imgWidth = img.width;
        var imgHeight = img.height;
        var newX = imgWidth;
        var newY = imgHeight;
        if (imgWidth > imgHeight) {
            if (imgWidth > Uppik.maxSize) {
                newX = Uppik.maxSize;
                newY = (Uppik.maxSize * imgHeight) / imgWidth;
            }
        } else {
            if (imgHeight > Uppik.maxSize) {
                newX = (Uppik.maxSize * imgWidth) / imgHeight;
                newY = Uppik.maxSize;
            }
        }
        var canvas = me.getCanvas();
        canvas.width = newX;
        canvas.height = newY;
        canvas.getContext("2d").drawImage(img, 0, 0, newX, newY);
        //finally upload data
        var raw = canvas.toDataURL('image/jpeg', me.quality);
        var imgData = raw.replace(/^data:image\/jpeg;base64,/, '');
        me.upload(imgData);
    };
    img.src = url;
}

Uppik.prototype.getCanvas = function() {
    if (!this.canvas) {
        this.canvas = document.createElement('canvas');
    }
    return this.canvas;
}
<commit_msg>only allow image<commit_after>'use strict;';

var Uppik = function(target, options) {
    if (!(target instanceof HTMLElement)) {
        target = document.getElementById(target);
    }
    this.target = target;
    this.options = {
        showState: true,
        fakeFileInput: false,
        fileInputClass: '',
        fileInputStyle: '',
        onSuccess: this.onSuccess,
        onUpload: this.onUpload,
        onError: this.onError
    };
    if (options) {
        for (key in options) {
            this.options[key] = options[key];
        }
    }
    this.currentFile = null;
    this.tryTime = 0;
    this.token = '';
    this.endpoint = '';
    this.quality = 0.5;
    this.fadeoutMessageInterval = null;
    this.hideMessageInterval = null;
    this.msgContainer = null;
    this.msgBody = null;

    //multiple file upload
    this.currentFileIndex = 1;
    this.totalFile = 1;

    this.init();
}

Uppik.inquiryUrl = 'http://www.uppik.net/api/inquiry';
Uppik.maxSize = 1024;
Uppik.messageTTL = 5000;
Uppik.maxTry = 10;
Uppik.allowedMimes = ["image/gif", "image/jpeg", "image/png", "image/jpg",];

Uppik.parseJson = function(str) {
    var output = {};
    try {
        output = JSON.parse(str);
    } catch (ex) {
        //nothing
    }
    return output;
}

Uppik.prototype.init = function() {
    this.initMessage();
    if (!this.checkRequirement()) {
        this.disableUpload();
        return;
    }
    this.initElements();
    this.inquiry();
}

Uppik.prototype.initMessage = function() {
    //message container
    var msgContainer = document.createElement('div');
    msgContainer.style.position = 'fixed';
    msgContainer.style.top = 0;
    msgContainer.style.left = 0;
    msgContainer.style.width = '100%';
    msgContainer.style.display = 'none';
    msgContainer.style.textAlign = 'center';
    msgContainer.style.backgroundColor = 'transparent';
    msgContainer.style.transition = 'opacity 0.5s ease';
    this.msgContainer = msgContainer;

    //message body
    var msgBody = document.createElement('span');
    msgBody.style.display = 'inline-block';
    msgBody.style.padding = '0.5em 1.5em';
    msgBody.style.marginTop = '0.5em';
    msgBody.style.borderRadius = '1em';
    msgBody.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
    this.msgBody = msgBody;

    msgContainer.appendChild(msgBody);
    document.body.appendChild(msgContainer);
}

Uppik.prototype.initElements = function() {
    // file input element
    var input = document.createElement('input');
    input.type = 'file';
    input.className = this.options.fileInputClass;
    input.style = this.options.fileInputStyle;
    input.accept = 'image/*';

    if (this.options.fakeFileInput) {
        this.target.style.position = 'relative';
        this.target.style.overflow = 'hidden';
        input.style.width = '1000px';
        input.style.height = '1000px';
        input.style.fontSize = '1000px';
        input.style.opacity = 0;
        input.style.position = 'absolute';
        input.style.left = '0px';
        input.style.top = '0px';
        input.style.cursor = 'pointer';
    }

    //attack file input to body
    this.target.appendChild(input);
    this.input = input;
    //bind events
    var me = this;
    input.onchange = function(e) {
        e.stopPropagation();
        me.onFileSelected(e);
    }
}

Uppik.prototype.disableUpload = function() {
    var me = this;
    this.target.onclick = function (e) {
        e.preventDefault();
        me.showMessage('This browser is not supported, lets switch to a modern browser.', true);
    }
}

Uppik.prototype.showMessage = function(msg, isError, keepShow) {
    if (this.fadeoutMessageInterval) {
        clearInterval(this.fadeoutMessageInterval);
        this.fadeoutMessageInterval = null;
    }
    if (this.hideMessageInterval) {
        clearInterval(this.hideMessageInterval);
        this.hideMessageInterval = null;
    }
    this.msgBody.innerText = msg;
    if (isError) {
        this.msgBody.style.color = '#ff0000';
    } else {
        this.msgBody.style.color = '#00ff00';
    }
    this.msgContainer.style.opacity = 1;
    this.msgContainer.style.display = 'block';
    var me = this;
    if (keepShow) {
        return;
    }
    this.hideMessageInterval = setInterval(function() {
        me.hideMessage();
    }, Uppik.messageTTL);
}

Uppik.prototype.hideMessage = function() {
    if (this.hideMessageInterval) {
        clearInterval(this.hideMessageInterval);
        this.hideMessageInterval = null;
    }
    this.msgContainer.style.opacity = 0;
    var me = this;
    this.fadeoutMessageInterval = setInterval(function() {
        me.msgContainer.style.display = 'none';
        if (me.fadeoutMessageInterval) {
            clearInterval(me.fadeoutMessageInterval);
            me.fadeoutMessageInterval = null;
        }
    }, 500);
}

Uppik.prototype._onSuccess = function(image) {
    this.input.value = null;
    this.input.removeAttribute('disabled');
    if (this.options.showState) {
        this.hideMessage();
    }
    this.options.onSuccess.apply(this, [image.url, image]);
}

Uppik.prototype._onUpload = function() {
    this.input.disabled = true;
    if (this.options.showState) {
        this.showMessage('Uploading...', false, true)
    }
    this.options.onUpload.apply(this, [this.currentFileIndex, this.totalFile]);
}

Uppik.prototype._onError = function(error) {
    this.input.value = null;
    this.input.removeAttribute('disabled');
    if (this.options.showState) {
        this.showMessage(error, true);
    }
    this.options.onError.apply(this, [error]);
}

Uppik.prototype.onFileSelected = function(event) {
    this.loadImage(event.target.files[0]);
}

Uppik.prototype.onSuccess = function(url, image) {
    console.log(image);
}

Uppik.prototype.onUpload = function(index, total) {
    console.log('Uploading...');
}

Uppik.prototype.onError = function(error) {
    console.log(error);
}

Uppik.prototype.inquiry = function() {
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('GET', Uppik.inquiryUrl, true);
        req.onreadystatechange = function() {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var data = Uppik.parseJson(req.responseText);
                    if (data.endpoint) {
                        me.endpoint = data.endpoint;
                        me.token = data.token;
                        me.quality = data.quality;
                        return;
                    }
                }
                me.showMessage('Cannot get information from server. Please try later.', true);
            }
        };
        req.send();
    }
}

Uppik.prototype.upload = function(data) {
    if (this.token == '' || this.enpoint == '') {
        return;
    }
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('POST', this.endpoint + '/upload', true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.onreadystatechange = function() {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var res = Uppik.parseJson(req.responseText);
                    if(res.image) {
                        //synchronous upload return url immediately
                        me._onSuccess(res.image);
                        return;
                    }
                    if (res.id) {
                        // asynchronous upload return file id
                        me.tryTime = 0;
                        me.currentFile = res.id;
                        me.delayQueryStatus();
                        return;
                    }
                }
                me._onError('Upload failed, please try again later.');
            }
        };
        this.hideMessage();
        req.send('token=' + this.token + '&data=' + encodeURI(data));
        this._onUpload();
    }
}

Uppik.prototype.checkRequirement = function() {
    if (typeof window.URL === 'undefined') {
        return false;
    }
    return true;
}

Uppik.prototype.queryStatus = function() {
    if (this.token == '' || this.endpoint == '') {
        return;
    }
    var req = new XMLHttpRequest();
    var me = this;
    if ('withCredentials' in req) {
        req.open('GET', this.endpoint + '/status?id=' + this.currentFile + '&token=' + this.token, true);
        req.onreadystatechange = function () {
            if (req.readyState === 4) {
                if (req.status >= 200 && req.status < 400) {
                    var res = Uppik.parseJson(req.responseText);
                    if (res.status == 'success') {
                        me._onSuccess(res.image);
                        return;
                    }
                    if (res.status == 'failed') {
                        me.showMessage(res.error, true);
                        return;
                    }
                }
                //error or pending
                me.tryTime++;
                if (me.tryTime < Uppik.maxTry) {
                    me.delayQueryStatus();
                } else {
                    me._onError('Upload timeout, please try again.');
                }
            }
        }
        req.send();
    }
}

Uppik.prototype.delayQueryStatus = function() {
    var me = this;
    setTimeout(function() {
        me.queryStatus()
    }, 1000);
}

Uppik.prototype.loadImage = function(file) {
    var url = URL.createObjectURL(file);
    var img = new Image();
    var me = this;
    if (Uppik.allowedMimes.indexOf(file.type) == -1) {
        return;
    }
    img.onload = function() {
        URL.revokeObjectURL(url);
        var imgWidth = img.width;
        var imgHeight = img.height;
        var newX = imgWidth;
        var newY = imgHeight;
        if (imgWidth > imgHeight) {
            if (imgWidth > Uppik.maxSize) {
                newX = Uppik.maxSize;
                newY = (Uppik.maxSize * imgHeight) / imgWidth;
            }
        } else {
            if (imgHeight > Uppik.maxSize) {
                newX = (Uppik.maxSize * imgWidth) / imgHeight;
                newY = Uppik.maxSize;
            }
        }
        var canvas = me.getCanvas();
        canvas.width = newX;
        canvas.height = newY;
        canvas.getContext("2d").drawImage(img, 0, 0, newX, newY);
        //finally upload data
        var raw = canvas.toDataURL('image/jpeg', me.quality);
        var imgData = raw.replace(/^data:image\/jpeg;base64,/, '');
        me.upload(imgData);
    };
    img.src = url;
}

Uppik.prototype.getCanvas = function() {
    if (!this.canvas) {
        this.canvas = document.createElement('canvas');
    }
    return this.canvas;
}
<|endoftext|>


<commit_before>// main function
var zpad = function (n, m, c) {
  if (!m) m = zpad._amount;
  if (!c) c = zpad._character;
  if (m < 1) m = 1;
  n = "" + n;
  m -= n.length;
  while (m-- > 0) n = c + n;
  return n;
}

// properties
zpad._amount = 2;
zpad._character = '0';

// 'amount' getter/setter
zpad.amount = function (m) {
  if (m) {
    zpad._amount = m;
    return zpad; // return main function for chaining
  } else {
    return zpad._amount;
  }
}

// 'character' getter/setter
zpad.character = function (c) {
  if (c) {
    zpad._character = c;
    return zpad; // return main function for chaining
  } else {
    return zpad._character;
  }
}

module.exports = zpad;<commit_msg>Remove useless line of code<commit_after>// main function
var zpad = function (n, m, c) {
  if (!m) m = zpad._amount;
  if (!c) c = zpad._character;
  n = "" + n;
  m -= n.length;
  while (m-- > 0) n = c + n;
  return n;
}

// properties
zpad._amount = 2;
zpad._character = '0';

// 'amount' getter/setter
zpad.amount = function (m) {
  if (m) {
    zpad._amount = m;
    return zpad; // return main function for chaining
  } else {
    return zpad._amount;
  }
}

// 'character' getter/setter
zpad.character = function (c) {
  if (c) {
    zpad._character = c;
    return zpad; // return main function for chaining
  } else {
    return zpad._character;
  }
}

module.exports = zpad;<|endoftext|>