<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { classnames } from '../../helpers/component';

const CURRENCIES = {
    USD: '$',
    EUR: '€',
    CHF: 'CHF'
};

const Price = ({ children: amount = 0, currency = '', className = '', divisor = 100, suffix = '' }) => {
    const value = Number(amount / divisor).toFixed(2);
    const c = {CURRENCIES[currency] || currency};
    const p = value < 0 ? - : null;
    const v = {Math.abs(value)};
    const s = suffix ? {suffix} : null;

    if (currency === 'USD') {
        return (

                {p}
                {c}
                {v}
                {s}

        ); // -$2/month
    }

    return (

            {p}
            {v}
            {currency ? <> {c}</> : null}
            {s}

    ); // -2 EUR/month
};

Price.propTypes = {
    currency: PropTypes.string,
    children: PropTypes.number,
    className: PropTypes.string,
    divisor: PropTypes.number,
    suffix: PropTypes.string
};

export default Price;
<commit_msg>Fix #248 - Display float price with 2 digit at least (#440)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { classnames } from '../../helpers/component';

const CURRENCIES = {
    USD: '$',
    EUR: '€',
    CHF: 'CHF'
};

const Price = ({ children: amount = 0, currency = '', className = '', divisor = 100, suffix = '' }) => {
    const fixedValue = Number(amount / divisor).toFixed(2);
    const absValue = Math.abs(fixedValue);
    const value = ~~fixedValue === absValue ? absValue : fixedValue;
    const c = {CURRENCIES[currency] || currency};
    const p = value < 0 ? - : null;
    const v = {value};
    const s = suffix ? {suffix} : null;

    if (currency === 'USD') {
        return (

                {p}
                {c}
                {v}
                {s}

        ); // -$2/month
    }

    return (

            {p}
            {v}
            {currency ? <> {c}</> : null}
            {s}

    ); // -2 EUR/month
};

Price.propTypes = {
    currency: PropTypes.string,
    children: PropTypes.number,
    className: PropTypes.string,
    divisor: PropTypes.number,
    suffix: PropTypes.string
};

export default Price;
<|endoftext|>


<commit_before>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Td from '../_Td';

import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';
import TableFragment from '../_statics/TableFragment';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {
                className, fragment, columns, rowIndex, data, isChecked, disabled,
                onCellClick
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(fragment, columns, rowIndex);

        return (

                {
                    columnsWithSpan && columnsWithSpan.map(({column, span}, colIndex) => column ?
                        <Td key={colIndex}
                            rowIndex={rowIndex}
                            colIndex={colIndex}
                            data={data}
                            className={column.bodyClassName}
                            style={column.bodyStyle}
                            renderer={column.bodyRenderer}
                            align={column.bodyAlign}
                            span={span}
                            disabled={disabled}
                            onCellClick={onCellClick}/>
                        :
                        null
                    )
                }

        );

    }
}

Tr.propTypes = {

    rowIndex: PropTypes.number,

    fragment: PropTypes.oneOf(Util.enumerateValue(TableFragment)),

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    className: PropTypes.string,

    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func

};

Tr.defaultProps = {
    rowIndex: 0,
    isChecked: false,
    disabled: false
};

export default Tr;
<commit_msg>update Tr<commit_after>/**
 * @file Tr component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Td from '../_Td';

import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import TableCalculation from '../_vendors/TableCalculation';

class Tr extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    handleClick = e => {
        const {data, rowIndex, disabled, onRowClick} = this.props;
        !disabled && onRowClick && onRowClick(data, rowIndex, e);
    };

    render() {

        const {
                className, columns, rowIndex, data, isChecked, disabled,
                onCellClick
            } = this.props,

            columnsWithSpan = TableCalculation.getColumnsWithSpan(TableFragment.BODY, columns, rowIndex);

        return (

                {
                    columnsWithSpan && columnsWithSpan.map(({column, span}, colIndex) => column ?
                        <Td key={colIndex}
                            rowIndex={rowIndex}
                            colIndex={colIndex}
                            data={data}
                            className={column.bodyClassName}
                            style={column.bodyStyle}
                            renderer={column.bodyRenderer}
                            align={column.bodyAlign}
                            span={span}
                            disabled={disabled}
                            onCellClick={onCellClick}/>
                        :
                        null
                    )
                }

        );

    }
}

Tr.propTypes = {

    rowIndex: PropTypes.number,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in header.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        headRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table.
         * (1) data key，example： 'id'
         * (2) data key tamplate，example：'${id} - ${name}'
         * (3) callback，example：function (rowData, rowIndex, colIndex) {return rowData.id;}
         */
        bodyRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in footer.
         * (1) string，example： 'id'
         * (2) callback，example：function (colIndex) {return colIndex;}
         */
        footRenderer: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.object,
    isChecked: PropTypes.bool,
    disabled: PropTypes.bool,
    className: PropTypes.string,

    onRowClick: PropTypes.func,
    onCellClick: PropTypes.func

};

Tr.defaultProps = {
    rowIndex: 0,
    isChecked: false,
    disabled: false
};

export default Tr;
<|endoftext|>


<commit_before>function init() {
    restore_options()
    document.getElementById('save').addEventListener('click', save_options);
    document.getElementById('default').addEventListener('click', defaultChanged);
    document.getElementById('chambers').addEventListener('keypress', chamberKeyPress);
}

// Saves options to chrome.storage
function save_options() {
    var chambers = document.getElementById('chambers').value;
    var override = !document.getElementById('default').checked;
    if(chambers=='0') {
        // they probably mean 1
        chambers = 1;
    }
    chrome.storage.sync.set({
        chamberCount: chambers,
        override: override
    }, function() {
        // Update status to let user know options were saved.
        var status = document.getElementById('status');
        status.textContent = 'Options saved.';
        setTimeout(function() {
            status.textContent = '';
        }, 750);
    });
}

// Restores select box and checkbox state using the preferences
// stored in chrome.storage.
function restore_options() {
    // Use default value color = 'red' and likesColor = true.
    chrome.storage.sync.get({
        chamberCount: '6',
        override: false
    }, function(items) {
        document.getElementById('chambers').value = items.chamberCount;
        document.getElementById('default').checked = !items.override;
        defaultChanged()
    });
}

function defaultChanged() {
    var isDefault = document.getElementById('default').checked;
    document.getElementById('chambers').disabled = isDefault;
}

function chamberKeyPress(event) {
    console.log('keypress');
    console.log(event);
    if (!(event.charCode >= 48 && event.charCode <= 57)) {
        event.preventDefault();
    }
}

document.addEventListener('DOMContentLoaded', init);
<commit_msg>Delete options.js<commit_after><|endoftext|>


<commit_before>import { ensureDoc } from "l3n";

import { error } from "./error";

import { seq, isSeq, forEach, filter, pipe } from "./seq";

import { zeroOrOne, exactlyOne } from "./seq/card";

import { isUndef } from "./util";

const _vnodeFromCx = (cx,node) => cx && "vnode" in cx ? cx.vnode : node.cx.vnode;

export function children($node) {
	const cx = this;
	return ensureDoc.bind(cx)($node).concatMap(node => {
		const vnode = _vnodeFromCx(cx,node);
		const values = node.type == 2 ? [node.inode] : node.values();
		const depth = node.depth + 1;
		return seq(values).map((inode, idx) => vnode(inode,node,depth,idx + 1));
	});
}

export function firstChild($node) {
	const cx = this;
	// assume ensureDoc returns the correct node
	return ensureDoc.bind(cx)($node).concatMap(node => {
		const vnode = _vnodeFromCx(cx,node);
		let next = node.first();
		return next ? seq(vnode(next,node,node.depth + 1, 0)) : seq();
	});
}

const _nextOrPrev = (cx,$node,dir) => {
	return ensureDoc.bind(cx)($node).concatMap(node => {
		const vnode = _vnodeFromCx(cx,node);
		var parent = node.parent;
		const sib = parent && parent[dir > 0 ? "next" : "previous"](node);
		return sib ? seq(vnode(sib, parent, node.depth, node.indexInParent + dir)) : seq();
	});
};

export function nextSibling($node){
	return _nextOrPrev(this, $node, 1);
}

export function previousSibling($node){
	return _nextOrPrev(this, $node, -1);
}

export function getDoc($node) {
	var cx = this;
	return ensureDoc.bind(cx)($node).concatMap(node => {
		do {
			node = node.parent;
		} while(node.parent);
		return seq(node);
	});
}

export function lastChild($node){
	var cx = this;
	return ensureDoc.bind(cx)($node).concatMap(node => {
		const last = node.last();
		const vnode = cx.vnode || node.cx.vnode;
		return last ? seq(vnode(last, node, node.depth, node.count() - 1)) : seq();
	});
}

export function parent($node) {
	if(!arguments.length) return Axis(parent);
	var cx = this;
	return ensureDoc.bind(cx)($node).concatMap(node => seq(node.parent));
}

export function self($f) {
	return zeroOrOne($f).map(f => {
		if(f.name !== "forEach" && f.name !== "filter") f = forEach(f);
		return Axis(node => node, f, 3);
	});
}

export const isVNode = n => !!n && n.__is_VNode;

const _isElement = n => isVNode(n) && n.type == 1;

const _isAttribute = n => isVNode(n) && n.type == 2;

const _isText = n => isVNode(n) && n.type == 3;

const _isList = n => isVNode(n) && n.type == 5;

const _isMap = n => isVNode(n) && n.type == 6;

const _isPI = n => isVNode(n) && n.type == 7;

const _isComment = n => isVNode(n) && n.type == 8;

const _isLiteral = n => isVNode(n) && n.type == 12;

export function cxFilter(iterable,f){
	return filter(iterable,function(v,k,i){
		if(!isSeq(v) && !isVNode(v)) v = seq(v);
		v.__cx = [k,i];
		return f(v,k,i);
	});
}

export const position = n => n.__cx ? n.__cx[0] + 1 : n.indexInParent;

export const last = n => n.__cx ? n.__cx[1].size : n.parent ? n.parent.size : 1;

const _isEq = (a,b) => a === b;

// TODO convert qname to integer when parent is array
function _nodeTest(typeTest,qnameOrKey) {
	var f;
	if (qnameOrKey === undefined) {
		f = typeTest;
	} else {
		var hasWildcard = /\*/.test(qnameOrKey);
		if (hasWildcard) {
			var regex = new RegExp(qnameOrKey.replace(/\*/, "(\\w[\\w0-9-_]*)"));
			f = n => {
				let isTuple = n.parent.type == 6;
				if(isTuple || n.name) {
					return typeTest(n) && regex.test(isTuple ? n.key : n.name);
				}
				return typeTest(n);
			};
		} else {
			f = n => {
				let isTuple = n.parent.type == 6;
				if(isTuple || n.name) {
					return _isEq(isTuple ? n.key : n.name,qnameOrKey) && typeTest(n);
				}
				return typeTest(n);
			};
			f.__Accessor = qnameOrKey;
		}
	}
	f.__is_NodeTypeTest = true;
	return f;
}

export function element(qname) {
	return _nodeTest(_isElement,qname);
}

export function list(keyOrIndex) {
	return _nodeTest(_isList,keyOrIndex);
}

export function map() {
	return _nodeTest(_isMap);
}

export function processingInstruction() {
	return _nodeTest(_isPI);
}

export function comment() {
	return _nodeTest(_isComment);
}

function _attrGet(key,$node){
	return seq($node).concatMap(node => {
		var entries;
		if (key !== null) {
			var val = node.attr(key);
			if (!val) return [];
			entries = [[key, val]];
		} else {
			entries = node.attrEntries();
		}
		return seq(entries).map(function (kv) {
			return node.vnode(node.pair(kv[0], kv[1]), node.parent, node.depth + 1, node.indexInParent);
		});
	});
}

// TODO make axis default, process node here, return seq(VNodeIterator)
// TODO maybe have Axis receive post-process func/seq
export function attribute($qname) {
	if(isUndef($qname)) $qname = "*";
	return exactlyOne($qname).map(qname => {
		var hasWildcard = /\*/.test(qname);
		// getter of attributes / pre-processor of attributes
		// TODO iterator!
		// filter of attributes
		var f;
		if (hasWildcard) {
			var regex = new RegExp(qname.replace(/\*/, "(\\w[\\w0-9-_]*)"));
			//	attrEntries returns tuples
			f = n => _isAttribute(n) && regex.test(n.name);
			// no direct access
			qname = null;
		} else {
			// name check provided by directAccess
			f = n => _isAttribute(n);
		}
		return Axis(_attrGet.bind(null,qname),filter(f),2);
	});
}

export function text() {
	var f = n => _isText(n) && !!n.value;
	f.__is_NodeTypeTest = true;
	return seq(f);
}

export function node() {
	var f = n => _isElement(n) || (_isText(n) && !!n.value);
	f.__is_NodeTypeTest = true;
	return seq(f);
}

// TODO create axis functions that return a function
// child(element(qname))
// works like a filter: filter(children(node|nodelist),n => element(qname,n))
// nextSibling(element()): filter(nextSibling(node|nodelist),n => element(undefined,n))
// filterOrGet: when f is called, and null or wildcard match was supplied as its qname parameter, call filter
// else call get
// if it is a seq, apply the function iteratively:
// we don't want to filter all elements from a seq, we want to retrieve all elements from elements in a seq
// final edge case: when node is of type array, and name is not an integer: filter
function Axis(g,f,type){
	return {
		__is_Axis: true,
		__type: type || 1,
		f:f,
		g:g
	};
}
export function child($f) {
	const cx = this;
	return forEach(zeroOrOne($f),f => {
		if(f.__is_NodeTypeTest){
			// this means it's a predicate, and the actual function should become a filter
			if(f.__Accessor) {
				// TODO this means we can try direct access on a node
			}
			f = filter(f);
		}
		return Axis(node => children.bind(cx)(node),f);
	});
}

export function siblingsOrSelf($node){
	var cx = this;
	return ensureDoc.bind(cx)($node).concatMap(node => children.bind(cx)(node.parent));
}

export function select($node, ...paths) {
	var cx = this;
	var boundEnsureDoc = ensureDoc.bind(cx);
	return seq(forEach(paths,
		path => _axify(path)))
		// we're passing $node here, because we want to update it every iteration
		.map(path => $node => {
			// make sure all paths are funcs
			// TODO skip self
			var skipCompare = path.__type == 2 || path.__type == 3;
			var f = path.f;
			// rebind step function to the context
			var bound = function bound(n) {
				return path.g(boundEnsureDoc(n));
			};
			if (!skipCompare) f = pipe(f, filter(_comparer()));
			return seq($node).concatMap(node => f(bound(node)));
		})
		.reduce(($node, changeFn) => changeFn($node),boundEnsureDoc($node))
		.concatAll();
}

function _comparer() {
	// dirty preserve state on function
	var f = function (node) {
		var has = f._checked.has(node);
		if (!has) f._checked.set(node,true);
		return !has;
	};
	f._checked = new WeakMap();
	return f;
}

/*
export function* select2(node,...paths) {
	// TODO
	// 1: node (or seq) is iterable, so get first as current context
	// 2: each function is a filter (either a node is returned or the process stops)
	// 3: pass each single result to a filter function, yielding a result for each
	var bed = ensureDoc.bind(this);
	var next = bed(node);
	var cx = next;
	if(next) {
		next = nextNode(next);
		while(next){
			for(var i=0,l=paths.length,path=paths[i]; i<l; i++){
				if(!isSeq(path)) path = seq(path);
				// process strings (can this be combined?)
				path = transform(path,compose(forEach(function(path){
					if(typeof path == "string") {
						var at = /^@/.test(path);
						if(at) path = path.substring(1);
						return at ? attribute(path) : element(path);
					}
					return [path];
				}),cat));
				var composed = compose.apply(null,path.toArray());
				let ret = composed.call(cx,next);
				if(node) {
					yield ret;
				} else {
					break;
				}
			}
		}
	}
}
*/
function _axify($path){
	return seq($path).concatMap(path => {
		if(!path.__is_Axis){
			// process strings (can this be combined?)
			if (typeof path == "string") {
				var at = /^@/.test(path);
				if (at) path = path.substring(1);
				return at ? attribute(path) : child(element(path));
			} else if(typeof path == "function"){
				if(path.__is_NodeTypeTest) return child(path);
				return self(path);
			} else {
				return error("XXX","Unknown axis provided");
			}
		}
		return seq(path);
	});
}

export function isEmptyNode(node){
	node = ensureDoc.bind(this)(node);
	if(!isVNode(node)) return false;
	if(_isText(node) || _isLiteral(node) || _isAttribute(node)) return node.value === undefined;
	return !node.count();
}

export function name($a) {
	if(!arguments.length) return name;
	return seq($a).concatMap(a => {
		if (!isVNode(a)) {
			return error("XXX","This is not a node");
		}
		if(a.type != 1) return seq();
		return seq(a.name);
	});
}
<commit_msg>updates to access based on unwrapping seq<commit_after>import { ensureDoc } from "l3n";

import { error } from "./error";

import { seq, isSeq, forEach, filter, pipe, switchMap, foldLeft } from "./seq";

import { isUndef } from "./util";

const _vnodeFromCx = (cx,node) => cx && "vnode" in cx ? cx.vnode : node.cx.vnode;

export function children($node) {
	const cx = this;
	return switchMap(ensureDoc.bind(cx)($node),node => {
		const vnode = _vnodeFromCx(cx,node);
		const values = node.type == 2 ? [node.inode] : node.values();
		const depth = node.depth + 1;
		return forEach(values,(inode, idx) => vnode(inode,node,depth,idx + 1));
	});
}

export function firstChild($node) {
	const cx = this;
	// assume ensureDoc returns the correct node
	return switchMap(ensureDoc.bind(cx)($node),node => {
		const vnode = _vnodeFromCx(cx,node);
		let next = node.first();
		return next ? seq(vnode(next,node,node.depth + 1, 0)) : seq();
	});
}

const _nextOrPrev = (cx,$node,dir) => {
	return switchMap(ensureDoc.bind(cx)($node),node => {
		const vnode = _vnodeFromCx(cx,node);
		var parent = node.parent;
		const sib = parent && parent[dir > 0 ? "next" : "previous"](node);
		return sib ? seq(vnode(sib, parent, node.depth, node.indexInParent + dir)) : seq();
	});
};

export function nextSibling($node){
	return _nextOrPrev(this, $node, 1);
}

export function previousSibling($node){
	return _nextOrPrev(this, $node, -1);
}

export function getDoc($node) {
	var cx = this;
	return switchMap(ensureDoc.bind(cx)($node),node => {
		do {
			node = node.parent;
		} while(node.parent);
		return seq(node);
	});
}

export function lastChild($node){
	var cx = this;
	return switchMap(ensureDoc.bind(cx)($node),node => {
		const last = node.last();
		const vnode = cx.vnode || node.cx.vnode;
		return last ? seq(vnode(last, node, node.depth, node.count() - 1)) : seq();
	});
}

export function parent($node) {
	if(!arguments.length) return Axis(parent);
	var cx = this;
	return switchMap(ensureDoc.bind(cx)($node),node => seq(node.parent));
}

export function self(f) {
	if(f.name !== "forEach" && f.name !== "filter") f = forEach(f);
	return Axis(node => node, f, 3);
}

export const isVNode = n => !!n && n.__is_VNode;

const _isElement = n => isVNode(n) && n.type == 1;

const _isAttribute = n => isVNode(n) && n.type == 2;

const _isText = n => isVNode(n) && n.type == 3;

const _isList = n => isVNode(n) && n.type == 5;

const _isMap = n => isVNode(n) && n.type == 6;

const _isPI = n => isVNode(n) && n.type == 7;

const _isComment = n => isVNode(n) && n.type == 8;

const _isLiteral = n => isVNode(n) && n.type == 12;

export function cxFilter(iterable,f){
	return filter(iterable,function(v,k,i){
		if(!isSeq(v) && !isVNode(v)) v = seq(v);
		v.__cx = [k,i];
		return f(v,k,i);
	});
}

export const position = n => n.__cx ? n.__cx[0] + 1 : n.indexInParent;

export const last = n => n.__cx ? n.__cx[1].size : n.parent ? n.parent.size : 1;

const _isEq = (a,b) => a === b;

// TODO convert qname to integer when parent is array
function _nodeTest(typeTest,qnameOrKey) {
	var f;
	if (qnameOrKey === undefined) {
		f = typeTest;
	} else {
		var hasWildcard = /\*/.test(qnameOrKey);
		if (hasWildcard) {
			var regex = new RegExp(qnameOrKey.replace(/\*/, "(\\w[\\w0-9-_]*)"));
			f = n => {
				let isTuple = n.parent.type == 6;
				if(isTuple || n.name) {
					return typeTest(n) && regex.test(isTuple ? n.key : n.name);
				}
				return typeTest(n);
			};
		} else {
			f = n => {
				let isTuple = n.parent.type == 6;
				if(isTuple || n.name) {
					return _isEq(isTuple ? n.key : n.name,qnameOrKey) && typeTest(n);
				}
				return typeTest(n);
			};
			f.__Accessor = qnameOrKey;
		}
	}
	f.__is_NodeTypeTest = true;
	return f;
}

export function element(qname) {
	return _nodeTest(_isElement,qname);
}

export function list(keyOrIndex) {
	return _nodeTest(_isList,keyOrIndex);
}

export function map() {
	return _nodeTest(_isMap);
}

export function processingInstruction() {
	return _nodeTest(_isPI);
}

export function comment() {
	return _nodeTest(_isComment);
}

function _attrGet(key,$node){
	return switchMap($node,node => {
		var entries;
		if (key !== null) {
			var val = node.attr(key);
			if (!val) return [];
			entries = [[key, val]];
		} else {
			entries = node.attrEntries();
		}
		return forEach(entries,function (kv) {
			return node.vnode(node.pair(kv[0], kv[1]), node.parent, node.depth + 1, node.indexInParent);
		});
	});
}

// TODO make axis default, process node here, return seq(VNodeIterator)
// TODO maybe have Axis receive post-process func/seq
export function attribute($qname) {
	if(isUndef($qname)) $qname = "*";
	return switchMap($qname,qname => {
		var hasWildcard = /\*/.test(qname);
		// getter of attributes / pre-processor of attributes
		// TODO iterator!
		// filter of attributes
		var f;
		if (hasWildcard) {
			var regex = new RegExp(qname.replace(/\*/, "(\\w[\\w0-9-_]*)"));
			//	attrEntries returns tuples
			f = n => _isAttribute(n) && regex.test(n.name);
			// no direct access
			qname = null;
		} else {
			// name check provided by directAccess
			f = n => _isAttribute(n);
		}
		return Axis(_attrGet.bind(null,qname),filter(f),2);
	});
}

export function text() {
	var f = n => _isText(n) && !!n.value;
	f.__is_NodeTypeTest = true;
	return f;
}

export function node() {
	var f = n => _isElement(n) || (_isText(n) && !!n.value);
	f.__is_NodeTypeTest = true;
	return seq(f);
}

// TODO create axis functions that return a function
// child(element(qname))
// works like a filter: filter(children(node|nodelist),n => element(qname,n))
// nextSibling(element()): filter(nextSibling(node|nodelist),n => element(undefined,n))
// filterOrGet: when f is called, and null or wildcard match was supplied as its qname parameter, call filter
// else call get
// if it is a seq, apply the function iteratively:
// we don't want to filter all elements from a seq, we want to retrieve all elements from elements in a seq
// final edge case: when node is of type array, and name is not an integer: filter
function Axis(g,f,type){
	return {
		__is_Axis: true,
		__type: type || 1,
		f:f,
		g:g
	};
}
export function child(f) {
	const cx = this;
	if(f.__is_NodeTypeTest){
		// this means it's a predicate, and the actual function should become a filter
		if(f.__Accessor) {
			// TODO this means we can try direct access on a node
		}
		f = filter(f);
	}
	return Axis(node => children.bind(cx)(node),f);
}

export function siblingsOrSelf($node){
	var cx = this;
	return switchMap(ensureDoc.bind(cx)($node),node => children.bind(cx)(node.parent));
}

export function select($node, ...paths) {
	var cx = this;
	var boundEnsureDoc = ensureDoc.bind(cx);
	return foldLeft(forEach(
		forEach(paths,path => _axify(path)),
		// we're passing $node here, because we want to update it every iteration
		path => $node => {
			// make sure all paths are funcs
			// TODO skip self
			var skipCompare = path.__type == 2 || path.__type == 3;
			var f = path.f;
			// rebind step function to the context
			var bound = function bound(n) {
				return path.g(boundEnsureDoc(n));
			};
			if (!skipCompare) f = pipe(f, filter(_comparer()));
			return switchMap($node,node => f(bound(node)));
		}),boundEnsureDoc($node),($node, changeFn) => changeFn($node));
}

function _comparer() {
	// dirty preserve state on function
	var f = function (node) {
		var has = f._checked.has(node);
		if (!has) f._checked.set(node,true);
		return !has;
	};
	f._checked = new WeakMap();
	return f;
}

function _axify($path){
	return switchMap($path,path => {
		if(!path.__is_Axis){
			// process strings (can this be combined?)
			if (typeof path == "string") {
				var at = /^@/.test(path);
				if (at) path = path.substring(1);
				return at ? attribute(path) : child(element(path));
			} else if(typeof path == "function"){
				if(path.__is_NodeTypeTest) return child(path);
				return self(path);
			} else {
				return error("XXX","Unknown axis provided");
			}
		}
		return seq(path);
	});
}

export function isEmptyNode(node){
	node = ensureDoc.bind(this)(node);
	if(!isVNode(node)) return false;
	if(_isText(node) || _isLiteral(node) || _isAttribute(node)) return node.value === undefined;
	return !node.count();
}

export function name($a) {
	if(!arguments.length) return name;
	return switchMap($a,a => {
		if (!isVNode(a)) {
			return error("XXX","This is not a node");
		}
		if(a.type != 1) return null;
		return a.name;
	});
}
<|endoftext|>


<commit_before>var get = Ember.get,
    set = Ember.set,
    setEach = Ember.setEach,
    addObserver = Ember.addObserver,
    removeObserver = Ember.removeObserver;

window.AutoSuggestComponent = Ember.Component.extend({
  actions: {
    addSelection: function(selection){
      set(this, 'query', '');
      get(this, 'destination').addObject(selection);
      set(this, 'selectionIndex', -1);
    },

    moveSelection: function(direction){
      var selectionIndex = get(this, 'selectionIndex'),
          isUp = direction === 'up',
          isDown = !isUp,
          displayResults = get(this, 'displayResults'),
          displayResultsLength = get(displayResults, 'length'),
          searchPath = get(this, 'searchPath'),
          hoverEl;

      displayResults.setEach('active', false);

      if(!displayResultsLength){
        set(this, 'selectionIndex', -1);
        return;
      }

      hoverEl = this.$('li.result.hover');

      if(hoverEl.length){
        var text = Ember.$('span', hoverEl).text(),
            selected = displayResults.find(function(item){
                          return get(item, searchPath) === text;
                       });

        selectionIndex = displayResults.indexOf(selected);

        this.$('ul.suggestions li').removeClass('hover');

        this.$('input.autosuggest').focus();
      }

      if(isUp && selectionIndex <= 0){
        selectionIndex =  0;
      }
      else if(isDown && selectionIndex === displayResultsLength -1){
        selectionIndex = displayResultsLength -1;
      }else if(isDown){
        selectionIndex++;
      }else{
        selectionIndex--;
      }

      var active = get(this, 'displayResults').objectAt(selectionIndex);

      set(this, 'selectionIndex', selectionIndex);

      set(active, 'active', true);
    },

    hideResults: function(){
      var displayResults = get(this, 'displayResults');

      set(this, 'selectionIndex', -1);

      if(!get(displayResults, 'length')){
        this.$('.no-results').addClass('hdn');
        return;
      }

      this.$('.results').addClass('hdn');
    },

    selectActive: function(){
      var selectionIndex = get(this, 'selectionIndex'),
          displayResultsLength = get(this, 'displayResults.length');

      if(!displayResultsLength){
        return;
      }

      var active = get(this, 'displayResults').find(function(item){
        return get(item, 'active');
      });

      if(!active){
        return;
      }

      this.send('addSelection', active);
    },

    removeSelection: function(item){
      get(this, 'destination').removeObject(item);
    },
  },

  classNameBindings: [':autosuggest'],
  minChars: 1,
  searchPath: 'name',
  query: null,
  selectionIndex: -1,

  init: function(){
    this._super.apply(this, arguments);
    addObserver(this, 'query', this.queryDidChange);
    set(this, 'displayResults', Ember.A());
  },

  didInsertElement: function(){
    Ember.assert('You must supply a source for the autosuggest component', get(this, 'source'));
    Ember.assert('You must supply a destination for the autosuggest component', get(this, 'destination'));

    this.$('ul.suggestions').on('mouseover', 'li', this.mouseOver.bind(this));
    this.$('ul.suggestions').on('mouseout', 'li', this.mouseOut.bind(this));
  },

  _queryPromise: function(query){
    var source = get(this, 'source'),
        searchPath = get(this, 'searchPath'),
        store = get(this, 'store');

    return Ember.RSVP.Promise(function(resolve, reject){
      if(('undefined' !== typeof DS) && (DS.Model.detect(source))){
        var queryExpression = {};

        queryExpression[searchPath] = query;

        var type = source.toString().humanize();

        store.find(type, queryExpression).then(resolve, reject);
      }
      else if(source.then){
        source.then(resolve, reject);
      }else{
        resolve(source);
      }
    });
  },

  queryDidChange: function(){
    var query = get(this, 'query'),
        displayResults = get(this, 'displayResults'),
        hasQuery = get(this, 'hasQuery'),
        self = this;

    if(!hasQuery){
      set(this, 'selectionIndex', -1);
      displayResults.clear();
      return;
    }

    this._queryPromise(query).then(function(results){
      self.processResults(query, results);
    },
    function(e){
      console.log(e.message);
      console.log(e.stack);
      throw e;
    });
  },

  processResults: function(query, source){
    var self = this,
        displayResults = get(this, 'displayResults');

    this.positionResults();

    var results = source.filter(function(item){
      return item.get(get(self, 'searchPath')).toLowerCase().search(query.toLowerCase()) !== -1;
    }).filter(function(item){
      return !get(self, 'destination').contains(item);
    });

    if(get(results, 'length') === 0){
      return displayResults.clear();
    }

    var searchPath = get(this, 'searchPath');

    displayResults.clear();

    displayResults.pushObjects(Ember.A(results.sort(function(a, b){
      return Ember.compare(get(a, searchPath), get(b, searchPath));
    })));
  },

  hasQuery: Ember.computed(function(){
    var query = get(this, 'query');

    if(query && query.length > get(this, 'minChars')){
      this.positionResults();
      return true;
    }

    return false;
  }).property('query'),

  mouseOver: function(evt){
    var el = this.$(evt.target);

    var active = get(this, 'displayResults').filter(function(item){
                   return get(item, 'active');
                 });

    if(active || active.length){
      active.setEach('active', false);
      set(this, 'selectionIndex', -1);
    }

    if(el.hasClass('result-name')){
      return;
    }

    this.$('ul.suggestions li').removeClass('hover');
    el.addClass('hover');
  },

  mouseOut: function(evt){
    var target = $(evt.target);

    if(target.parents('ul').hasClass('suggestions')){
      return;
    }

    this.$('ul.suggestions li').removeClass('hover');
  },

  positionResults: function(){
    var results = this.$('.results');

    var input = this.$('input.autosuggest'),
        suggestions = this.$('ul.suggestions'),
        selections = this.$('ul.selections'),
        position = input.position();

    results.removeClass('hdn');

    suggestions.css('position', 'absolute');
    suggestions.css('left', position.left);
    suggestions.css('top', position.top + input.height() + 7);
    suggestions.css('width', this.$('ul.selections').outerWidth() - position.left);
  },

  autosuggest: Ember.TextField.extend({
    KEY_DOWN: 40,
    KEY_UP: 38,
    COMMA: 188,
    TAB: 9,
    ENTER: 13,
    ESCAPE: 27,

    init: function(){
      this._super.apply(this, arguments);

      var allowedKeyCodes = Ember.A([this.KEY_UP, this.KEY_DOWN, this.COMMA, this.TAB, this.ENTER, this.ESCAPE]);
      this.set('allowedKeyCodes', allowedKeyCodes);
    },

    keyDown: function(e){
      var keyCode = e.keyCode;

      if(!this.get('allowedKeyCodes').contains(keyCode)){
        return;
      }

      var controller = get(this, 'controller');

      switch(keyCode){
        case this.KEY_UP:
          this.sendAction('moveSelection', 'up');
          break;
        case this.KEY_DOWN:
          this.sendAction('moveSelection', 'down');
          break;
        case this.ENTER:
          controller.sendAction('selectActive');
          break;
        case this.ESCAPE:
          this.sendAction('hideResults');
          break;
        default:
          console.log(keyCode);
      }
    },
  }),
});
<commit_msg>put width in temp<commit_after>var get = Ember.get,
    set = Ember.set,
    setEach = Ember.setEach,
    addObserver = Ember.addObserver,
    removeObserver = Ember.removeObserver;

window.AutoSuggestComponent = Ember.Component.extend({
  actions: {
    addSelection: function(selection){
      set(this, 'query', '');
      get(this, 'destination').addObject(selection);
      set(this, 'selectionIndex', -1);
    },

    moveSelection: function(direction){
      var selectionIndex = get(this, 'selectionIndex'),
          isUp = direction === 'up',
          isDown = !isUp,
          displayResults = get(this, 'displayResults'),
          displayResultsLength = get(displayResults, 'length'),
          searchPath = get(this, 'searchPath'),
          hoverEl;

      displayResults.setEach('active', false);

      if(!displayResultsLength){
        set(this, 'selectionIndex', -1);
        return;
      }

      hoverEl = this.$('li.result.hover');

      if(hoverEl.length){
        var text = Ember.$('span', hoverEl).text(),
            selected = displayResults.find(function(item){
                          return get(item, searchPath) === text;
                       });

        selectionIndex = displayResults.indexOf(selected);

        this.$('ul.suggestions li').removeClass('hover');

        this.$('input.autosuggest').focus();
      }

      if(isUp && selectionIndex <= 0){
        selectionIndex =  0;
      }
      else if(isDown && selectionIndex === displayResultsLength -1){
        selectionIndex = displayResultsLength -1;
      }else if(isDown){
        selectionIndex++;
      }else{
        selectionIndex--;
      }

      var active = get(this, 'displayResults').objectAt(selectionIndex);

      set(this, 'selectionIndex', selectionIndex);

      set(active, 'active', true);
    },

    hideResults: function(){
      var displayResults = get(this, 'displayResults');

      set(this, 'selectionIndex', -1);

      if(!get(displayResults, 'length')){
        this.$('.no-results').addClass('hdn');
        return;
      }

      this.$('.results').addClass('hdn');
    },

    selectActive: function(){
      var selectionIndex = get(this, 'selectionIndex'),
          displayResultsLength = get(this, 'displayResults.length');

      if(!displayResultsLength){
        return;
      }

      var active = get(this, 'displayResults').find(function(item){
        return get(item, 'active');
      });

      if(!active){
        return;
      }

      this.send('addSelection', active);
    },

    removeSelection: function(item){
      get(this, 'destination').removeObject(item);
    },
  },

  classNameBindings: [':autosuggest'],
  minChars: 1,
  searchPath: 'name',
  query: null,
  selectionIndex: -1,

  init: function(){
    this._super.apply(this, arguments);
    addObserver(this, 'query', this.queryDidChange);
    set(this, 'displayResults', Ember.A());
  },

  didInsertElement: function(){
    Ember.assert('You must supply a source for the autosuggest component', get(this, 'source'));
    Ember.assert('You must supply a destination for the autosuggest component', get(this, 'destination'));

    this.$('ul.suggestions').on('mouseover', 'li', this.mouseOver.bind(this));
    this.$('ul.suggestions').on('mouseout', 'li', this.mouseOut.bind(this));
  },

  _queryPromise: function(query){
    var source = get(this, 'source'),
        searchPath = get(this, 'searchPath'),
        store = get(this, 'store');

    return Ember.RSVP.Promise(function(resolve, reject){
      if(('undefined' !== typeof DS) && (DS.Model.detect(source))){
        var queryExpression = {};

        queryExpression[searchPath] = query;

        var type = source.toString().humanize();

        store.find(type, queryExpression).then(resolve, reject);
      }
      else if(source.then){
        source.then(resolve, reject);
      }else{
        resolve(source);
      }
    });
  },

  queryDidChange: function(){
    var query = get(this, 'query'),
        displayResults = get(this, 'displayResults'),
        hasQuery = get(this, 'hasQuery'),
        self = this;

    if(!hasQuery){
      set(this, 'selectionIndex', -1);
      displayResults.clear();
      return;
    }

    this._queryPromise(query).then(function(results){
      self.processResults(query, results);
    },
    function(e){
      console.log(e.message);
      console.log(e.stack);
      throw e;
    });
  },

  processResults: function(query, source){
    var self = this,
        displayResults = get(this, 'displayResults');

    this.positionResults();

    var results = source.filter(function(item){
      return item.get(get(self, 'searchPath')).toLowerCase().search(query.toLowerCase()) !== -1;
    }).filter(function(item){
      return !get(self, 'destination').contains(item);
    });

    if(get(results, 'length') === 0){
      return displayResults.clear();
    }

    var searchPath = get(this, 'searchPath');

    displayResults.clear();

    displayResults.pushObjects(Ember.A(results.sort(function(a, b){
      return Ember.compare(get(a, searchPath), get(b, searchPath));
    })));
  },

  hasQuery: Ember.computed(function(){
    var query = get(this, 'query');

    if(query && query.length > get(this, 'minChars')){
      this.positionResults();
      return true;
    }

    return false;
  }).property('query'),

  mouseOver: function(evt){
    var el = this.$(evt.target);

    var active = get(this, 'displayResults').filter(function(item){
                   return get(item, 'active');
                 });

    if(active || active.length){
      active.setEach('active', false);
      set(this, 'selectionIndex', -1);
    }

    if(el.hasClass('result-name')){
      return;
    }

    this.$('ul.suggestions li').removeClass('hover');
    el.addClass('hover');
  },

  mouseOut: function(evt){
    var target = $(evt.target);

    if(target.parents('ul').hasClass('suggestions')){
      return;
    }

    this.$('ul.suggestions li').removeClass('hover');
  },

  positionResults: function(){
    var results = this.$('.results');

    var input = this.$('input.autosuggest'),
        suggestions = this.$('ul.suggestions'),
        selections = this.$('ul.selections'),
        position = input.position();

    results.removeClass('hdn');

    suggestions.css('position', 'absolute');
    suggestions.css('left', position.left);
    suggestions.css('top', position.top + input.height() + 7);

    var width = this.$('ul.selections').outerWidth() - position.left;

    suggestions.css('width', width);
  },

  autosuggest: Ember.TextField.extend({
    KEY_DOWN: 40,
    KEY_UP: 38,
    COMMA: 188,
    TAB: 9,
    ENTER: 13,
    ESCAPE: 27,

    init: function(){
      this._super.apply(this, arguments);

      var allowedKeyCodes = Ember.A([this.KEY_UP, this.KEY_DOWN, this.COMMA, this.TAB, this.ENTER, this.ESCAPE]);
      this.set('allowedKeyCodes', allowedKeyCodes);
    },

    keyDown: function(e){
      var keyCode = e.keyCode;

      if(!this.get('allowedKeyCodes').contains(keyCode)){
        return;
      }

      var controller = get(this, 'controller');

      switch(keyCode){
        case this.KEY_UP:
          this.sendAction('moveSelection', 'up');
          break;
        case this.KEY_DOWN:
          this.sendAction('moveSelection', 'down');
          break;
        case this.ENTER:
          controller.sendAction('selectActive');
          break;
        case this.ESCAPE:
          this.sendAction('hideResults');
          break;
        default:
          console.log(keyCode);
      }
    },
  }),
});
<|endoftext|>


<commit_before>// The functions in this file are intended to be used to test non-complex polygons
// where horizontal lines that overlap the polygon only cross the polygon twice.
function createPolygon(vertices) {
    var xCoordinates = vertices.map( function(p) { return p.x; } );
    var yCoordinates = vertices.map( function(p) { return p.y; } );
    return {
        vertices: vertices,
        minX: Math.min.apply(null, xCoordinates),
        maxX: Math.max.apply(null, xCoordinates),
        minY: Math.min.apply(null, yCoordinates),
        maxY: Math.max.apply(null, yCoordinates)
    };
}

function createRegularPolygonVertices(size, nSides)
{
    var radius = size / (2 * Math.cos(Math.PI / nSides));
    var inset = size / 2 + 20;
    var vertices = [];

    for (var i = 0; i < nSides/2; i++) {
        var a = (1 + 2*i) * (Math.PI / nSides);
        vertices[i] = {x: Math.floor(radius * Math.cos(a)), y: Math.floor(radius * Math.sin(a))};
        vertices[nSides - i - 1] = {x: vertices[i].x, y: -vertices[i].y}  // Y axis symmetry
    }

    for (var i = 0; i < nSides; i++) {
        vertices[i].x += inset;
        vertices[i].y += inset;
    }

    return vertices;
}

// Return two X intercepts of the horizontal line at y. We're assuming that the polygon
// has 0 or 2 intercepts for all y. Of course this isn't true for polygons in general,
// just the ones used by the test cases supported by this file.

function polygonXIntercepts(polygon, y) {
    var vertices = polygon.vertices;
    var foundXIntercept = false;
    var interceptsMinX, interceptsMaxX;

    for(var i = 0; i < vertices.length; i++) {
        var v1 = vertices[i];
        var v2 = vertices[(i + 1) % vertices.length];

        if (Math.max(v1.y, v2.y) < y || Math.min(v1.y, v2.y) > y)
            continue;

        if (v1.y == y && v2.y == y) {  // horizontal edge
            if (y != polygon.maxY)
                continue;

            if (!foundXIntercept) {
                interceptsMinX = Math.min(v1.x, v2.x);
                interceptsMaxX = Math.max(v1.x, v2.x);
                foundXIntercept = true;
            }
            else {
                interceptsMinX = Math.min(v1.x, v2.x, interceptsMinX);
                interceptsMaxX = Math.max(v1.x, v2.x, interceptsMaxX);
            }
        }
        else {
            var interceptX;

            if (v1.y == y)
                interceptX = v1.x;
            else if (v2.y == y)
                interceptX = v2.x;
            else
                interceptX = ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x;

            if (!foundXIntercept) {
                interceptsMinX = interceptsMaxX = interceptX;
                foundXIntercept = true;
            }
            else {
                interceptsMinX = Math.min(interceptX, interceptsMinX);
                interceptsMaxX = Math.max(interceptX, interceptsMaxX);
            }
        }
    }

    if (!foundXIntercept)
        return [];

    return [SubPixelLayout.snapToLayoutUnit(interceptsMinX), SubPixelLayout.snapToLayoutUnit(interceptsMaxX)];
}

function polygonLineIntercepts(polygon, y, lineHeight) {
    var i1 = polygonXIntercepts(polygon, y);
    var i2 = polygonXIntercepts(polygon, y + lineHeight);

    if (i1.length < 2)
        return i2;
    if (i2.length < 2)
        return i1;

    return [Math.max(i1[0], i2[0]), Math.min(i1[1], i2[1])];
}

// Generate an "X X ..." string that contains enough characters to fill the polygon. Each
// character occupies a lineHeight size square cell, the top of first line of characters is aligned
// with the the polygon's bounds minimum Y value, and each line of characters fills the interior
// of the polygon.

function generatePolygonContentString(polygon, lineheight) {
    var result = "";

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var lengthInCells = Math.floor(xIntercepts[1] / lineHeight) - Math.ceil(xIntercepts[0] / lineHeight);
        for (var i = 0; i < lengthInCells / 2; i++)
            result += "X ";  // all lines end in a space, to enable line breaking
    }

    return result;
}

function generatePolygonShapeInsideElement(elementId, stylesheet, polygon, lineHeight) {
    var verticesString = polygon.vertices.map( function(p) { return p.x + "px " + p.y + "px"; } ).join(", ");
    stylesheet.insertRule("#" + elementId + " { "
        + "shape-inside: polygon(" + verticesString + "); "
        + "width: " + polygon.maxX + "px; "
        + "height: " + polygon.maxY + "px; "
        + "font: " + lineHeight + "px/1 Ahem, sans-serif; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0;}");

    var text = document.createTextNode(generatePolygonContentString(polygon, lineHeight));
    var p = document.createElement("p");
    p.appendChild(text);

    var element = document.getElementById(elementId);
    element.appendChild(p);
}

function generatePolygonSVGElements(elementId, stylesheet, polygon, lineHeight) {
    var svgNS = "http://www.w3.org/2000/svg";

    var svgPolygon = document.createElementNS(svgNS, "polygon");
    svgPolygon.setAttribute("points", polygon.vertices.map( function(p) { return p.x + "," + p.y; } ).join(" "));
    svgPolygon.setAttribute("fill", "#636363");

    var svgElement = document.getElementById(elementId);
    svgElement.style.width = polygon.maxX + "px";
    svgElement.style.height = polygon.maxY + "px";
    svgElement.appendChild(svgPolygon);
}

function simulatePolygonShape(elementId, stylesheet, polygon, lineHeight) {
    var width = Math.ceil(polygon.maxX);
    var height = Math.ceil(polygon.maxY);
    stylesheet.insertRule("#" + elementId + " { width: " + width + "px; height: " + height + "px; font: " + lineHeight + "px/1 Ahem, sans-serif;}");
    stylesheet.insertRule("#" + elementId + " .float { height: " + lineHeight + "px; }");
    stylesheet.insertRule("#" + elementId + " .left { float: left; clear: left; }");
    stylesheet.insertRule("#" + elementId + " .right { float: right; clear: right; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0; }");

    var element = document.getElementById(elementId);

    var paddingTop = document.createElement("div");
    paddingTop.setAttribute("class", "float left");
    paddingTop.style.width = width + "px";
    paddingTop.style.height = polygon.minY + "px";
    element.appendChild(paddingTop);

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var left = xIntercepts[0];
        var right = xIntercepts[1];

        var paddingLeft = document.createElement("div");
        paddingLeft.setAttribute("class", "float left");
        paddingLeft.style.width = left + "px";
        element.appendChild(paddingLeft);

        var paddingRight = document.createElement("div");
        paddingRight.setAttribute("class", "float right");
        paddingRight.style.width = width - right + "px";
        element.appendChild(paddingRight);
    }
}

function generateSimulatedPolygonShapeInsideElement(elementId, stylesheet, polygon, lineHeight) {
    var width = Math.ceil(polygon.maxX);
    var height = Math.ceil(polygon.maxY);

    stylesheet.insertRule("#" + elementId + " { width: " + width + "px; height: " + height + "px; font: " + lineHeight + "px/1 Ahem, sans-serif;}");
    stylesheet.insertRule("#" + elementId + " .float { height: " + lineHeight + "px; }");
    stylesheet.insertRule("#" + elementId + " .left { float: left; clear: left; }");
    stylesheet.insertRule("#" + elementId + " .right { float: right; clear: right; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0; }");

    var element = document.getElementById(elementId);

    var paddingTop = document.createElement("div");
    paddingTop.setAttribute("class", "float left");
    paddingTop.style.width = width + "px";
    paddingTop.style.height = polygon.minY + "px";
    element.appendChild(paddingTop);

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var left = xIntercepts[0];
        var right = xIntercepts[1];

        var paddingLeft = document.createElement("div");
        paddingLeft.setAttribute("class", "float left");
        paddingLeft.style.width = left + "px";
        element.appendChild(paddingLeft);

        var paddingRight = document.createElement("div");
        paddingRight.setAttribute("class", "float right");
        paddingRight.style.width = width - right + "px";
        element.appendChild(paddingRight);
    }

    var text = document.createTextNode(generatePolygonContentString(polygon, lineHeight));
    var p = document.createElement("p");
    p.appendChild(text);

    var element = document.getElementById(elementId);
    element.appendChild(p);
}

function positionInformativeText(elementId, stylesheet, polygon, lineHeight)
{
    stylesheet.insertRule("#" + elementId + " { position: absolute; top: " + (polygon.maxY + lineHeight) + "px;}");
}

function createPolygonShapeInsideTestCase() {
    var stylesheet = document.getElementById("stylesheet").sheet;
    var polygon = createPolygon(vertices);
    generatePolygonShapeInsideElement("polygon-shape-inside", stylesheet, polygon, lineHeight);
    generatePolygonSVGElements("polygon-svg-shape", stylesheet, polygon, lineHeight);
    positionInformativeText("informative-text", stylesheet, polygon, lineHeight)
}

function createPolygonShapeInsideTestCaseExpected() {
    var stylesheet = document.getElementById("stylesheet").sheet;
    var polygon = createPolygon(vertices);
    generateSimulatedPolygonShapeInsideElement("polygon-shape-inside", stylesheet, polygon, lineHeight);
    generatePolygonSVGElements("polygon-svg-shape", stylesheet, polygon, lineHeight);
    positionInformativeText("informative-text", stylesheet, polygon, lineHeight)
}
<commit_msg>Fix typo in simple-polygon.js LayoutTest helper<commit_after>// The functions in this file are intended to be used to test non-complex polygons
// where horizontal lines that overlap the polygon only cross the polygon twice.
function createPolygon(vertices) {
    var xCoordinates = vertices.map( function(p) { return p.x; } );
    var yCoordinates = vertices.map( function(p) { return p.y; } );
    return {
        vertices: vertices,
        minX: Math.min.apply(null, xCoordinates),
        maxX: Math.max.apply(null, xCoordinates),
        minY: Math.min.apply(null, yCoordinates),
        maxY: Math.max.apply(null, yCoordinates)
    };
}

function createRegularPolygonVertices(size, nSides)
{
    var radius = size / (2 * Math.cos(Math.PI / nSides));
    var inset = size / 2 + 20;
    var vertices = [];

    for (var i = 0; i < nSides/2; i++) {
        var a = (1 + 2*i) * (Math.PI / nSides);
        vertices[i] = {x: Math.floor(radius * Math.cos(a)), y: Math.floor(radius * Math.sin(a))};
        vertices[nSides - i - 1] = {x: vertices[i].x, y: -vertices[i].y}  // Y axis symmetry
    }

    for (var i = 0; i < nSides; i++) {
        vertices[i].x += inset;
        vertices[i].y += inset;
    }

    return vertices;
}

// Return two X intercepts of the horizontal line at y. We're assuming that the polygon
// has 0 or 2 intercepts for all y. Of course this isn't true for polygons in general,
// just the ones used by the test cases supported by this file.

function polygonXIntercepts(polygon, y) {
    var vertices = polygon.vertices;
    var foundXIntercept = false;
    var interceptsMinX, interceptsMaxX;

    for(var i = 0; i < vertices.length; i++) {
        var v1 = vertices[i];
        var v2 = vertices[(i + 1) % vertices.length];

        if (Math.max(v1.y, v2.y) < y || Math.min(v1.y, v2.y) > y)
            continue;

        if (v1.y == y && v2.y == y) {  // horizontal edge
            if (y != polygon.maxY)
                continue;

            if (!foundXIntercept) {
                interceptsMinX = Math.min(v1.x, v2.x);
                interceptsMaxX = Math.max(v1.x, v2.x);
                foundXIntercept = true;
            }
            else {
                interceptsMinX = Math.min(v1.x, v2.x, interceptsMinX);
                interceptsMaxX = Math.max(v1.x, v2.x, interceptsMaxX);
            }
        }
        else {
            var interceptX;

            if (v1.y == y)
                interceptX = v1.x;
            else if (v2.y == y)
                interceptX = v2.x;
            else
                interceptX = ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x;

            if (!foundXIntercept) {
                interceptsMinX = interceptsMaxX = interceptX;
                foundXIntercept = true;
            }
            else {
                interceptsMinX = Math.min(interceptX, interceptsMinX);
                interceptsMaxX = Math.max(interceptX, interceptsMaxX);
            }
        }
    }

    if (!foundXIntercept)
        return [];

    return [SubPixelLayout.snapToLayoutUnit(interceptsMinX), SubPixelLayout.snapToLayoutUnit(interceptsMaxX)];
}

function polygonLineIntercepts(polygon, y, lineHeight) {
    var i1 = polygonXIntercepts(polygon, y);
    var i2 = polygonXIntercepts(polygon, y + lineHeight);

    if (i1.length < 2)
        return i2;
    if (i2.length < 2)
        return i1;

    return [Math.max(i1[0], i2[0]), Math.min(i1[1], i2[1])];
}

// Generate an "X X ..." string that contains enough characters to fill the polygon. Each
// character occupies a lineHeight size square cell, the top of first line of characters is aligned
// with the the polygon's bounds minimum Y value, and each line of characters fills the interior
// of the polygon.

function generatePolygonContentString(polygon, lineHeight) {
    var result = "";

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var lengthInCells = Math.floor(xIntercepts[1] / lineHeight) - Math.ceil(xIntercepts[0] / lineHeight);
        for (var i = 0; i < lengthInCells / 2; i++)
            result += "X ";  // all lines end in a space, to enable line breaking
    }

    return result;
}

function generatePolygonShapeInsideElement(elementId, stylesheet, polygon, lineHeight) {
    var verticesString = polygon.vertices.map( function(p) { return p.x + "px " + p.y + "px"; } ).join(", ");
    stylesheet.insertRule("#" + elementId + " { "
        + "shape-inside: polygon(" + verticesString + "); "
        + "width: " + polygon.maxX + "px; "
        + "height: " + polygon.maxY + "px; "
        + "font: " + lineHeight + "px/1 Ahem, sans-serif; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0;}");

    var text = document.createTextNode(generatePolygonContentString(polygon, lineHeight));
    var p = document.createElement("p");
    p.appendChild(text);

    var element = document.getElementById(elementId);
    element.appendChild(p);
}

function generatePolygonSVGElements(elementId, stylesheet, polygon, lineHeight) {
    var svgNS = "http://www.w3.org/2000/svg";

    var svgPolygon = document.createElementNS(svgNS, "polygon");
    svgPolygon.setAttribute("points", polygon.vertices.map( function(p) { return p.x + "," + p.y; } ).join(" "));
    svgPolygon.setAttribute("fill", "#636363");

    var svgElement = document.getElementById(elementId);
    svgElement.style.width = polygon.maxX + "px";
    svgElement.style.height = polygon.maxY + "px";
    svgElement.appendChild(svgPolygon);
}

function simulatePolygonShape(elementId, stylesheet, polygon, lineHeight) {
    var width = Math.ceil(polygon.maxX);
    var height = Math.ceil(polygon.maxY);
    stylesheet.insertRule("#" + elementId + " { width: " + width + "px; height: " + height + "px; font: " + lineHeight + "px/1 Ahem, sans-serif;}");
    stylesheet.insertRule("#" + elementId + " .float { height: " + lineHeight + "px; }");
    stylesheet.insertRule("#" + elementId + " .left { float: left; clear: left; }");
    stylesheet.insertRule("#" + elementId + " .right { float: right; clear: right; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0; }");

    var element = document.getElementById(elementId);

    var paddingTop = document.createElement("div");
    paddingTop.setAttribute("class", "float left");
    paddingTop.style.width = width + "px";
    paddingTop.style.height = polygon.minY + "px";
    element.appendChild(paddingTop);

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var left = xIntercepts[0];
        var right = xIntercepts[1];

        var paddingLeft = document.createElement("div");
        paddingLeft.setAttribute("class", "float left");
        paddingLeft.style.width = left + "px";
        element.appendChild(paddingLeft);

        var paddingRight = document.createElement("div");
        paddingRight.setAttribute("class", "float right");
        paddingRight.style.width = width - right + "px";
        element.appendChild(paddingRight);
    }
}

function generateSimulatedPolygonShapeInsideElement(elementId, stylesheet, polygon, lineHeight) {
    var width = Math.ceil(polygon.maxX);
    var height = Math.ceil(polygon.maxY);

    stylesheet.insertRule("#" + elementId + " { width: " + width + "px; height: " + height + "px; font: " + lineHeight + "px/1 Ahem, sans-serif;}");
    stylesheet.insertRule("#" + elementId + " .float { height: " + lineHeight + "px; }");
    stylesheet.insertRule("#" + elementId + " .left { float: left; clear: left; }");
    stylesheet.insertRule("#" + elementId + " .right { float: right; clear: right; }");
    stylesheet.insertRule("#" + elementId + " p { -webkit-margin-before: 0; word-wrap: break-word; letter-spacing: 0; }");

    var element = document.getElementById(elementId);

    var paddingTop = document.createElement("div");
    paddingTop.setAttribute("class", "float left");
    paddingTop.style.width = width + "px";
    paddingTop.style.height = polygon.minY + "px";
    element.appendChild(paddingTop);

    for (var y = polygon.minY; y < polygon.maxY; y += lineHeight) {
        var xIntercepts = polygonLineIntercepts(polygon, y, lineHeight);
        var left = xIntercepts[0];
        var right = xIntercepts[1];

        var paddingLeft = document.createElement("div");
        paddingLeft.setAttribute("class", "float left");
        paddingLeft.style.width = left + "px";
        element.appendChild(paddingLeft);

        var paddingRight = document.createElement("div");
        paddingRight.setAttribute("class", "float right");
        paddingRight.style.width = width - right + "px";
        element.appendChild(paddingRight);
    }

    var text = document.createTextNode(generatePolygonContentString(polygon, lineHeight));
    var p = document.createElement("p");
    p.appendChild(text);

    var element = document.getElementById(elementId);
    element.appendChild(p);
}

function positionInformativeText(elementId, stylesheet, polygon, lineHeight)
{
    stylesheet.insertRule("#" + elementId + " { position: absolute; top: " + (polygon.maxY + lineHeight) + "px;}");
}

function createPolygonShapeInsideTestCase() {
    var stylesheet = document.getElementById("stylesheet").sheet;
    var polygon = createPolygon(vertices);
    generatePolygonShapeInsideElement("polygon-shape-inside", stylesheet, polygon, lineHeight);
    generatePolygonSVGElements("polygon-svg-shape", stylesheet, polygon, lineHeight);
    positionInformativeText("informative-text", stylesheet, polygon, lineHeight)
}

function createPolygonShapeInsideTestCaseExpected() {
    var stylesheet = document.getElementById("stylesheet").sheet;
    var polygon = createPolygon(vertices);
    generateSimulatedPolygonShapeInsideElement("polygon-shape-inside", stylesheet, polygon, lineHeight);
    generatePolygonSVGElements("polygon-svg-shape", stylesheet, polygon, lineHeight);
    positionInformativeText("informative-text", stylesheet, polygon, lineHeight)
}
<|endoftext|>


<commit_before>var applicationMock;
var ApplicationMock = Ember.Object.extend();

var containerMock;
var ContainerMock = Ember.Object.extend({
  init: function() {
    this.registrations = {};
    this.injections = [];
  },
  register: function(name, factory, options) {
    this.registrations[name] = {
      factory: factory,
      options: options
    };
  },
  inject: function(target, property, name) {
    var registration = this.registrations[name];
    if (registration) {
      this.injections.push({
        target:   target,
        property: property,
        object:   registration.factory
      });
    }
  },
  lookup: function(name) {
    return Ember.tryInvoke(this.registrations[name], 'factory');
  }
});

var authorizerMock;
var AuthorizerMock = Ember.Object.extend({
  authorize: function() {
    this.authorized = true;
  }
});
AuthorizerMock.reopenClass({
  create: function(options) {
    return (authorizerMock = this._super(options));
  }
});

var ajaxPrefilterMock;
var AjaxPrefilterMock = Ember.Object.extend({
  ajaxPrefilterCapture: function(prefilter) {
    this.registeredAjaxPrefilter = prefilter;
  }
});

module('Ember.SimpleAuth', {
  originalAjaxPrefilter: Ember.$.ajaxPrefilter,
  setup: function() {
    applicationMock       = ApplicationMock.create();
    containerMock         = ContainerMock.create();
    ajaxPrefilterMock     = AjaxPrefilterMock.create();
    Ember.$.ajaxPrefilter = Ember.$.proxy(ajaxPrefilterMock.ajaxPrefilterCapture, ajaxPrefilterMock);
  },
  teardown: function() {
    Ember.$.ajaxPrefilter = this.originalAjaxPrefilter;
  }
});

test('assigns the authentication route', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authenticationRoute: 'somewhere' });

  equal(Ember.SimpleAuth.authenticationRoute, 'somewhere', 'Ember.SimpleAuth assigns authenticationRoute when specified for setup.');
});

test('assigns the route after authentication', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterAuthentication: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterAuthentication, 'somewhere', 'Ember.SimpleAuth assigns routeAfterAuthentication when specified for setup.');
});

test('assigns the route after session invalidation', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterInvalidation: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterInvalidation, 'somewhere', 'Ember.SimpleAuth assigns routeAfterInvalidation when specified for setup.');
});

test('injects the session in models, views, controllers and routes', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock);

  Ember.$.each(['model', 'view', 'controller', 'view'], function(i, component) {
    var injection = Ember.$.grep(containerMock.injections, function(injection) {
      return injection.target === component;
    })[0];

    equal(injection.object.constructor, Ember.SimpleAuth.Session, 'Ember.SimpleAuth injects the session into ' + component + '.');
    equal(injection.property, 'session', 'Ember.SimpleAuth makes the session available as "session" in ' + component + '.');
  });
});

test('assigns the store and container to the session', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { store: Ember.SimpleAuth.Stores.Ephemeral });

  var session = containerMock.injections[0].object;

  equal(session.container, containerMock, 'Ember.SimpleAuth assigns the container to the session.');
  equal(session.store.constructor, Ember.SimpleAuth.Stores.Ephemeral, 'Ember.SimpleAuth assigns the correct store to the session.');
});

test('registers an AJAX prefilter that authorizes requests', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authorizer: AuthorizerMock });

  ajaxPrefilterMock.registeredAjaxPrefilter({}, {}, {});
  ok(authorizerMock.authorized, "Ember.SimpleAuth registers an AJAX prefilter that authorizes requests that fo the the application's origin.");

  authorizerMock.authorized = false;
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(!authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that does not authorize cross-origin requests.');

  Ember.SimpleAuth.setup(containerMock, applicationMock, { crossOriginWhitelist: ['https://a.different.domain:1234'], authorizer: AuthorizerMock, store: Ember.SimpleAuth.Stores.Ephemeral });
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that authorizes cross-origin requests when the origin is in the crossOriginWhitelist.');
});
<commit_msg>fixed test<commit_after>var containerMock;
var ContainerMock = Ember.Object.extend({
  init: function() {
    this.registrations = {};
  },
  register: function(name, factory, options) {
    this.registrations[name] = {
      factory: factory,
      options: options
    };
  },
  lookup: function(name) {
    return this.registrations[name];
  }
});

var applicationMock;
var ApplicationMock = Ember.Object.extend({
  init: function() {
    this.injections = [];
  },
  inject: function(target, property, name) {
    var registration = this.container.lookup(name);
    if (registration) {
      this.injections.push({
        target:   target,
        property: property,
        object:   registration.factory
      });
    }
  }
});

var authorizerMock;
var AuthorizerMock = Ember.Object.extend({
  authorize: function() {
    this.authorized = true;
  }
});
AuthorizerMock.reopenClass({
  create: function(options) {
    return (authorizerMock = this._super(options));
  }
});

var ajaxPrefilterMock;
var AjaxPrefilterMock = Ember.Object.extend({
  ajaxPrefilterCapture: function(prefilter) {
    this.registeredAjaxPrefilter = prefilter;
  }
});

module('Ember.SimpleAuth', {
  originalAjaxPrefilter: Ember.$.ajaxPrefilter,
  setup: function() {
    containerMock         = ContainerMock.create();
    applicationMock       = ApplicationMock.create({ container: containerMock });
    ajaxPrefilterMock     = AjaxPrefilterMock.create();
    Ember.$.ajaxPrefilter = Ember.$.proxy(ajaxPrefilterMock.ajaxPrefilterCapture, ajaxPrefilterMock);
  },
  teardown: function() {
    Ember.$.ajaxPrefilter = this.originalAjaxPrefilter;
  }
});

test('assigns the authentication route', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authenticationRoute: 'somewhere' });

  equal(Ember.SimpleAuth.authenticationRoute, 'somewhere', 'Ember.SimpleAuth assigns authenticationRoute when specified for setup.');
});

test('assigns the route after authentication', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterAuthentication: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterAuthentication, 'somewhere', 'Ember.SimpleAuth assigns routeAfterAuthentication when specified for setup.');
});

test('assigns the route after session invalidation', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { routeAfterInvalidation: 'somewhere' });

  equal(Ember.SimpleAuth.routeAfterInvalidation, 'somewhere', 'Ember.SimpleAuth assigns routeAfterInvalidation when specified for setup.');
});

test('injects the session in models, views, controllers and routes', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock);

  Ember.$.each(['model', 'view', 'controller', 'view'], function(i, component) {
    var injection = Ember.$.grep(applicationMock.injections, function(injection) {
      return injection.target === component;
    })[0];

    equal(injection.object.constructor, Ember.SimpleAuth.Session, 'Ember.SimpleAuth injects the session into ' + component + '.');
    equal(injection.property, 'session', 'Ember.SimpleAuth makes the session available as "session" in ' + component + '.');
  });
});

test('assigns the store and container to the session', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { store: Ember.SimpleAuth.Stores.Ephemeral });

  var session = applicationMock.injections[0].object;

  equal(session.container, containerMock, 'Ember.SimpleAuth assigns the container to the session.');
  equal(session.store.constructor, Ember.SimpleAuth.Stores.Ephemeral, 'Ember.SimpleAuth assigns the correct store to the session.');
});

test('registers an AJAX prefilter that authorizes requests', function() {
  Ember.SimpleAuth.setup(containerMock, applicationMock, { authorizer: AuthorizerMock });

  ajaxPrefilterMock.registeredAjaxPrefilter({}, {}, {});
  ok(authorizerMock.authorized, "Ember.SimpleAuth registers an AJAX prefilter that authorizes requests that fo the the application's origin.");

  authorizerMock.authorized = false;
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(!authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that does not authorize cross-origin requests.');

  Ember.SimpleAuth.setup(containerMock, applicationMock, { crossOriginWhitelist: ['https://a.different.domain:1234'], authorizer: AuthorizerMock, store: Ember.SimpleAuth.Stores.Ephemeral });
  ajaxPrefilterMock.registeredAjaxPrefilter({ url: 'https://a.different.domain:1234' }, {}, {});
  ok(authorizerMock.authorized, 'Ember.SimpleAuth registers an AJAX prefilter that authorizes cross-origin requests when the origin is in the crossOriginWhitelist.');
});
<|endoftext|>


<commit_before>// Parts Endpoints

const Router = require('koa-router');
const capsules = require('../../controllers/v3/capsules');

const v3 = new Router({
  prefix: '/v3',
});

// Returns all capsule information
v3.get('/caps', capsules.all);

// Returns specific capsule information
v3.get('/caps/:cap', capsules.one);

module.exports = v3;
<commit_msg>corrected incorrect route path for v3 capsules<commit_after>// Parts Endpoints

const Router = require('koa-router');
const capsules = require('../../controllers/v3/capsules');

const v3 = new Router({
  prefix: '/v3',
});

// Returns all capsule information
v3.get('/capsules', capsules.all);

// Returns specific capsule information
v3.get('/capsules/:cap', capsules.one);

module.exports = v3;
<|endoftext|>


<commit_before>angular.module("application").controller("DrivingController", [
    "$scope", "SmartAdresseSource", "DriveReport", "PersonalAddress", "AddressFormatter", "PersonalAddressType", "Person", "PersonEmployments", "Rate", "LicensePlate", "NotificationService", "$modal", "$state", "Address", "Route", function ($scope, SmartAdresseSource, DriveReport, PersonalAddress, AddressFormatter, PersonalAddressType, Person, PersonEmployments, Rate, LicensePlate, NotificationService, $modal, $state, Address, Route) {

        $scope.DriveReport = new DriveReport();
        $scope.canSubmitDriveReport = true;
        $scope.Routes = [];
        $scope.IsRoute = false;

        $scope.test = function(e) {
            var index = e.sender.selectedIndex;

            if (index == 0) {
                $scope.IsRoute = false;
                $scope.DriveReport.Addresses = [];

                $scope.DriveReport.Addresses.push({ Name: "", Save: false });
                $scope.DriveReport.Addresses.push({ Name: "", Save: false });
                return;
            }

            $scope.IsRoute = true;

            var route = $scope.Routes[index - 1];

            var lastIndex = route.Points.length - 1;

            $scope.DriveReport.Addresses = [];

            angular.forEach($scope.Routes[index - 1].Points, function(value, key) {
                $scope.DriveReport.Addresses.push({ Name: value.StreetName + " " + value.StreetNumber + ", " + value.ZipCode + " " + value.Town, Save: false });
            });
        }

        $scope.Person = Person.get({ id: 1 }, function() {
            Address.get({ query: "$filter=PersonId eq " + $scope.Person.Id + " and Type eq Core.DomainModel.PersonalAddressType'Standard'" }, function (data) {
                var temp = [{value: "Vælg fast adresse"}];

                angular.forEach(data.value, function (value, key) {
                    temp.push({ value: value.StreetName + " " + value.StreetNumber + ", " + value.ZipCode + " " + value.Town });
                });

                $scope.PersonalAddresses = temp;
            });

            Route.get({ query: "&filter=PersonId eq " + 1 }, function (data) {

                var temp = [{ addressOne: "", addressTwo: "", viaPointCounr: "", presentation: "" }];

                angular.forEach(data.value, function (value, key) {
                    var one = value.Points[0].StreetName + " " + value.Points[0].StreetNumber + ", " + value.Points[0].ZipCode + " " + value.Points[0].Town;
                    var two = value.Points[value.Points.length - 1].StreetName + " " + value.Points[value.Points.length - 1].StreetNumber + ", " + value.Points[value.Points.length - 1].ZipCode + " " + value.Points[value.Points.length - 1].Town;
                    var count = value.Points.length - 2;
                    temp.push({ addressOne: one, addressTwo: two, viaPointCount: count, presentation: value.Description + ": " + one + " -> " + two + " | Antal viapunkter: " + count, routeId: value.Id });
                    $scope.Routes.push(value);
                });

                $scope.PersonalRoutes = temp;
            });
        });

        $scope.FourKmRule = {}
        $scope.FourKmRule.Using = false;

        $scope.KmRate = Rate.ThisYearsRates(function () {
            $scope.KmRateDropDown.dataSource.read();
        });

        $scope.Employments = PersonEmployments.get({ id: 1 }, function () {
            $scope.PositionDropDown.dataSource.read();
        });

        $scope.Licenseplates = LicensePlate.get({ id: 1 }, function (data) {
            if (data.length > 0) {
                $scope.LicenseplateDropDown.dataSource.read();
                $scope.canSubmitDriveReport = data.length > 0;
            } else {
                $scope.openNoLicensePlateModal();
            }
        });

        $scope.DriveReport.Addresses = [];

        $scope.DriveReport.Addresses.push({ Name: "", Personal: "", Save: false });
        $scope.DriveReport.Addresses.push({ Name: "", Personal: "", Save: false });

        $scope.SmartAddress = SmartAdresseSource;

        $scope.DriveReport.Date = new Date();

        $scope.DateOptions = {
            start: "month"
        };

        $scope.DrivenKilometers = 0;
        $scope.TransportAllowance = 0;
        $scope.RemainingKilometers = 0;
        $scope.PayoutAmount = 0;

        $scope.Save = function () {

            var driveReport = new DriveReport();

            // Prepare all data to  be uploaded
            driveReport.Purpose = $scope.DriveReport.Purpose;
            driveReport.DriveDateTimestamp = Math.floor($scope.DriveReport.Date.getTime() / 1000);
            driveReport.KmRate = parseFloat($scope.DriveReport.KmRate);
            driveReport.TFCode = $scope.DriveReport.TFCode;
            driveReport.KilometerAllowance = $scope.DriveReport.KilometerAllowance;
            driveReport.Distance = 0;
            driveReport.AmountToReimburse = 0;
            driveReport.Licenseplate = $scope.DriveReport.Licenseplate;
            driveReport.PersonId = $scope.Person.Id;
            driveReport.Status = "Pending";
            driveReport.CreatedDateTimestamp = Math.floor(Date.now() / 1000);
            driveReport.EditedDateTimestamp = driveReport.CreatedDateTimestamp;
            driveReport.Comment = "";
            driveReport.ClosedDateTimestamp = 0;
            driveReport.ProcessedDateTimestamp = 0;
            driveReport.EmploymentId = $scope.DriveReport.Position;

            // These two should be removed, they are in a future branch
            //driveReport.Fullname = "";
            //driveReport.Timestamp = "";

            if ($scope.DriveReport.KilometerAllowance === "Read") {

                driveReport.Distance = $scope.DriveReport.ReadDistance;

                if ($scope.DriveReport.StartOrEndedAtHome === 'Started') {
                    driveReport.StartsAtHome = true;
                    driveReport.EndsAtHome = false;
                } else if ($scope.DriveReport.StartOrEndedAtHome === 'Ended') {
                    driveReport.StartsAtHome = false;
                    driveReport.EndsAtHome = true;
                } else if ($scope.DriveReport.StartOrEndedAtHome === 'Both') {
                    driveReport.StartsAtHome = true;
                    driveReport.EndsAtHome = true;
                } else {
                    driveReport.StartsAtHome = false;
                    driveReport.EndsAtHome = false;
                }
            } else {

                driveReport.StartsAtHome = false;
                driveReport.EndsAtHome = false;

                driveReport.DriveReportPoints = [];

                angular.forEach($scope.DriveReport.Addresses, function (address, key) {

                    var tempAddress = (address.Personal.length != 0) ? address.Personal : address.Name;

                    var currentAddress = new PersonalAddress(AddressFormatter.fn(tempAddress));

                    driveReport.DriveReportPoints.push({
                        StreetName: currentAddress.StreetName,
                        StreetNumber: currentAddress.StreetNumber,
                        ZipCode: currentAddress.ZipCode,
                        Town: currentAddress.Town,
                        Description: "",
                        Latitude: "",
                        Longitude: ""
                    });

                });

                if (typeof $scope.DriveReport.RoundTrip !== "undefined" && $scope.DriveReport.RoundTrip === true) {
                    for (var i = driveReport.DriveReportPoints.length - 1; i > 0; --i) {
                        driveReport.DriveReportPoints.push(driveReport.DriveReportPoints[i]);
                    }
                }

                // go through addresses and see which is going to be saved
                angular.forEach($scope.DriveReport.Addresses, function (address, key) {

                    if (address.Save) {
                        var personalAddress = new PersonalAddress(AddressFormatter.fn(address.Name));

                        personalAddress.PersonId = $scope.Person.Id;
                        personalAddress.Type = PersonalAddressType.Standard;
                        personalAddress.Longitude = "";
                        personalAddress.Latitude = "";
                        personalAddress.Description = "";

                        delete personalAddress.Id;

                        personalAddress.$save();
                    }
                });
            }

            if (typeof $scope.DriveReport.FourKmRule !== "undefined" && $scope.DriveReport.FourKmRule.Using === true) {
                driveReport.FourKmRule = true;
            } else {
                driveReport.FourKmRule = false;
            }

            driveReport.$save(function (response) {
                // success
                $scope.DrivenKilometers = response.Distance;
                $scope.TransportAllowance = 0;
                $scope.RemainingKilometers = 0;
                $scope.PayoutAmount = response.AmountToReimburse;

                NotificationService.AutoFadeNotification("success", "Success", "Din kørselsindberetning blev gemt");

            }, function (response) {
                // failure
                NotificationService.AutoFadeNotification("danger", "Fejl", "Din kørselsindberetning blev ikke gemt");
            });
        };

        $scope.AddViapoint = function () {
            var temp = $scope.DriveReport.Addresses.pop();
            $scope.DriveReport.Addresses.push({ Name: "", Personal:"", Save: false });
            $scope.DriveReport.Addresses.push(temp);
        };

        $scope.Remove = function (array, index) {
            array.splice(index, 1);
        };

        $scope.openNoLicensePlateModal = function () {

            var modalInstance = $modal.open({
                templateUrl: '/App/Driving/noLicensePlateModal.html',
                controller: 'noLicensePlateModalController',
                //size: size,
                backdrop: 'static',
                resolve: {

                }
            });

            modalInstance.result.then(function () {
                $state.go("settings");
            }, function () {

            });
        };
    }
]);<commit_msg>Changed DrivingView to show adress.Description instead of actual address.<commit_after>angular.module("application").controller("DrivingController", [
    "$scope", "SmartAdresseSource", "DriveReport", "PersonalAddress", "AddressFormatter", "PersonalAddressType", "Person", "PersonEmployments", "Rate", "LicensePlate", "NotificationService", "$modal", "$state", "Address", "Route", function ($scope, SmartAdresseSource, DriveReport, PersonalAddress, AddressFormatter, PersonalAddressType, Person, PersonEmployments, Rate, LicensePlate, NotificationService, $modal, $state, Address, Route) {

        $scope.DriveReport = new DriveReport();
        $scope.canSubmitDriveReport = true;
        $scope.Routes = [];
        $scope.IsRoute = false;

        $scope.test = function(e) {
            var index = e.sender.selectedIndex;

            if (index == 0) {
                $scope.IsRoute = false;
                $scope.DriveReport.Addresses = [];

                $scope.DriveReport.Addresses.push({ Name: "", Save: false });
                $scope.DriveReport.Addresses.push({ Name: "", Save: false });
                return;
            }

            $scope.IsRoute = true;

            var route = $scope.Routes[index - 1];

            var lastIndex = route.Points.length - 1;

            $scope.DriveReport.Addresses = [];

            angular.forEach($scope.Routes[index - 1].Points, function(value, key) {
                $scope.DriveReport.Addresses.push({ Name: value.StreetName + " " + value.StreetNumber + ", " + value.ZipCode + " " + value.Town, Save: false });
            });
        }

        $scope.Person = Person.get({ id: 1 }, function() {
            Address.get({ query: "$filter=PersonId eq " + $scope.Person.Id + " and Type eq Core.DomainModel.PersonalAddressType'Standard'" }, function (data) {
                var temp = [{value: "Vælg fast adresse"}];

                angular.forEach(data.value, function (value, key) {
                    temp.push({ value: value.Description });
                });

                $scope.PersonalAddresses = temp;
            });

            Route.get({ query: "&filter=PersonId eq " + 1 }, function (data) {

                var temp = [{ addressOne: "", addressTwo: "", viaPointCounr: "", presentation: "" }];

                angular.forEach(data.value, function (value, key) {
                    var one = value.Points[0].StreetName + " " + value.Points[0].StreetNumber + ", " + value.Points[0].ZipCode + " " + value.Points[0].Town;
                    var two = value.Points[value.Points.length - 1].StreetName + " " + value.Points[value.Points.length - 1].StreetNumber + ", " + value.Points[value.Points.length - 1].ZipCode + " " + value.Points[value.Points.length - 1].Town;
                    var count = value.Points.length - 2;
                    temp.push({ addressOne: one, addressTwo: two, viaPointCount: count, presentation: value.Description + ": " + one + " -> " + two + " | Antal viapunkter: " + count, routeId: value.Id });
                    $scope.Routes.push(value);
                });

                $scope.PersonalRoutes = temp;
            });
        });

        $scope.FourKmRule = {}
        $scope.FourKmRule.Using = false;

        $scope.KmRate = Rate.ThisYearsRates(function () {
            $scope.KmRateDropDown.dataSource.read();
        });

        $scope.Employments = PersonEmployments.get({ id: 1 }, function () {
            $scope.PositionDropDown.dataSource.read();
        });

        $scope.Licenseplates = LicensePlate.get({ id: 1 }, function (data) {
            if (data.length > 0) {
                $scope.LicenseplateDropDown.dataSource.read();
                $scope.canSubmitDriveReport = data.length > 0;
            } else {
                $scope.openNoLicensePlateModal();
            }
        });

        $scope.DriveReport.Addresses = [];

        $scope.DriveReport.Addresses.push({ Name: "", Personal: "", Save: false });
        $scope.DriveReport.Addresses.push({ Name: "", Personal: "", Save: false });

        $scope.SmartAddress = SmartAdresseSource;

        $scope.DriveReport.Date = new Date();

        $scope.DateOptions = {
            start: "month"
        };

        $scope.DrivenKilometers = 0;
        $scope.TransportAllowance = 0;
        $scope.RemainingKilometers = 0;
        $scope.PayoutAmount = 0;

        $scope.Save = function () {

            var driveReport = new DriveReport();

            // Prepare all data to  be uploaded
            driveReport.Purpose = $scope.DriveReport.Purpose;
            driveReport.DriveDateTimestamp = Math.floor($scope.DriveReport.Date.getTime() / 1000);
            driveReport.KmRate = parseFloat($scope.DriveReport.KmRate);
            driveReport.TFCode = $scope.DriveReport.TFCode;
            driveReport.KilometerAllowance = $scope.DriveReport.KilometerAllowance;
            driveReport.Distance = 0;
            driveReport.AmountToReimburse = 0;
            driveReport.Licenseplate = $scope.DriveReport.Licenseplate;
            driveReport.PersonId = $scope.Person.Id;
            driveReport.Status = "Pending";
            driveReport.CreatedDateTimestamp = Math.floor(Date.now() / 1000);
            driveReport.EditedDateTimestamp = driveReport.CreatedDateTimestamp;
            driveReport.Comment = "";
            driveReport.ClosedDateTimestamp = 0;
            driveReport.ProcessedDateTimestamp = 0;
            driveReport.EmploymentId = $scope.DriveReport.Position;

            // These two should be removed, they are in a future branch
            //driveReport.Fullname = "";
            //driveReport.Timestamp = "";

            if ($scope.DriveReport.KilometerAllowance === "Read") {

                driveReport.Distance = $scope.DriveReport.ReadDistance;

                if ($scope.DriveReport.StartOrEndedAtHome === 'Started') {
                    driveReport.StartsAtHome = true;
                    driveReport.EndsAtHome = false;
                } else if ($scope.DriveReport.StartOrEndedAtHome === 'Ended') {
                    driveReport.StartsAtHome = false;
                    driveReport.EndsAtHome = true;
                } else if ($scope.DriveReport.StartOrEndedAtHome === 'Both') {
                    driveReport.StartsAtHome = true;
                    driveReport.EndsAtHome = true;
                } else {
                    driveReport.StartsAtHome = false;
                    driveReport.EndsAtHome = false;
                }
            } else {

                driveReport.StartsAtHome = false;
                driveReport.EndsAtHome = false;

                driveReport.DriveReportPoints = [];

                angular.forEach($scope.DriveReport.Addresses, function (address, key) {

                    var tempAddress = (address.Personal.length != 0) ? address.Personal : address.Name;

                    var currentAddress = new PersonalAddress(AddressFormatter.fn(tempAddress));

                    driveReport.DriveReportPoints.push({
                        StreetName: currentAddress.StreetName,
                        StreetNumber: currentAddress.StreetNumber,
                        ZipCode: currentAddress.ZipCode,
                        Town: currentAddress.Town,
                        Description: "",
                        Latitude: "",
                        Longitude: ""
                    });

                });

                if (typeof $scope.DriveReport.RoundTrip !== "undefined" && $scope.DriveReport.RoundTrip === true) {
                    for (var i = driveReport.DriveReportPoints.length - 1; i > 0; --i) {
                        driveReport.DriveReportPoints.push(driveReport.DriveReportPoints[i]);
                    }
                }

                // go through addresses and see which is going to be saved
                angular.forEach($scope.DriveReport.Addresses, function (address, key) {

                    if (address.Save) {
                        var personalAddress = new PersonalAddress(AddressFormatter.fn(address.Name));

                        personalAddress.PersonId = $scope.Person.Id;
                        personalAddress.Type = PersonalAddressType.Standard;
                        personalAddress.Longitude = "";
                        personalAddress.Latitude = "";
                        personalAddress.Description = "";

                        delete personalAddress.Id;

                        personalAddress.$save();
                    }
                });
            }

            if (typeof $scope.DriveReport.FourKmRule !== "undefined" && $scope.DriveReport.FourKmRule.Using === true) {
                driveReport.FourKmRule = true;
            } else {
                driveReport.FourKmRule = false;
            }

            driveReport.$save(function (response) {
                // success
                $scope.DrivenKilometers = response.Distance;
                $scope.TransportAllowance = 0;
                $scope.RemainingKilometers = 0;
                $scope.PayoutAmount = response.AmountToReimburse;

                NotificationService.AutoFadeNotification("success", "Success", "Din kørselsindberetning blev gemt");

            }, function (response) {
                // failure
                NotificationService.AutoFadeNotification("danger", "Fejl", "Din kørselsindberetning blev ikke gemt");
            });
        };

        $scope.AddViapoint = function () {
            var temp = $scope.DriveReport.Addresses.pop();
            $scope.DriveReport.Addresses.push({ Name: "", Personal:"", Save: false });
            $scope.DriveReport.Addresses.push(temp);
        };

        $scope.Remove = function (array, index) {
            array.splice(index, 1);
        };

        $scope.openNoLicensePlateModal = function () {

            var modalInstance = $modal.open({
                templateUrl: '/App/Driving/noLicensePlateModal.html',
                controller: 'noLicensePlateModalController',
                //size: size,
                backdrop: 'static',
                resolve: {

                }
            });

            modalInstance.result.then(function () {
                $state.go("settings");
            }, function () {

            });
        };
    }
]);<|endoftext|>