<commit_before>iD.Graph = function(other, mutable) {
    if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);

    if (other instanceof iD.Graph) {
        var base = other.base();
        this.entities = _.assign(Object.create(base.entities), other.entities);
        this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
        this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
        this.inherited = true;

    } else {
        if (_.isArray(other)) {
            var entities = {};
            for (var i = 0; i < other.length; i++) {
                entities[other[i].id] = other[i];
            }
            other = entities;
        }
        this.entities = Object.create({});
        this._parentWays = Object.create({});
        this._parentRels = Object.create({});
        this.rebase(other || {});
    }

    this.transients = {};
    this._childNodes = {};

    if (!mutable) {
        this.freeze();
    }
};

iD.Graph.prototype = {
    entity: function(id) {
        return this.entities[id];
    },

    transient: function(entity, key, fn) {
        var id = entity.id,
            transients = this.transients[id] ||
            (this.transients[id] = {});

        if (transients[key] !== undefined) {
            return transients[key];
        }

        return transients[key] = fn.call(entity);
    },

    parentWays: function(entity) {
        return _.map(this._parentWays[entity.id], _.bind(this.entity, this));
    },

    isPoi: function(entity) {
        return this.parentWays(entity).length === 0;
    },

    parentRelations: function(entity) {
        return _.map(this._parentRels[entity.id], _.bind(this.entity, this));
        var ent, id, parents;

        return this._parentRels[entity.id] || [];
    },

    childNodes: function(entity) {
        if (this._childNodes[entity.id])
            return this._childNodes[entity.id];

        var nodes = [];
        for (var i = 0, l = entity.nodes.length; i < l; i++) {
            nodes[i] = this.entity(entity.nodes[i]);
        }

        return (this._childNodes[entity.id] = nodes);
    },

    base: function() {
        return {
            'entities': iD.util.getPrototypeOf(this.entities),
            'parentWays': iD.util.getPrototypeOf(this._parentWays),
            'parentRels': iD.util.getPrototypeOf(this._parentRels)
        };
    },

    // Unlike other graph methods, rebase mutates in place. This is because it
    // is used only during the history operation that merges newly downloaded
    // data into each state. To external consumers, it should appear as if the
    // graph always contained the newly downloaded data.
    rebase: function(entities) {
        var i, keys;
        // Merging of data only needed if graph is the base graph
        if (!this.inherited) {
            _.defaults(this.base().entities, entities);
            for (i in entities) {
                this._updateCalculated(undefined, entities[i], this.base().parentWays, this.base().parentRels);
            }
        }

        keys = Object.keys(this._parentWays);
        for (i = 0; i < keys.length; i++) {
            this._parentWays[keys[i]] = _.unique((this._parentWays[keys[i]] || [])
                    .concat(this.base().parentWays[keys[i]] || []));
        }

        keys = Object.keys(this._parentRels);
        for (i = 0; i < keys.length; i++) {
            this._parentRels[keys[i]] = _.unique((this._parentRels[keys[i]] || [])
                    .concat(this.base().parentRels[keys[i]] || []));
        }
    },

    // Updates calculated properties (parentWays, parentRels) for the specified change
    _updateCalculated: function(oldentity, entity, parentWays, parentRels) {

        parentWays = parentWays || this._parentWays;
        parentRels = parentRels || this._parentRels;

        var type = entity && entity.type || oldentity && oldentity.type,
            removed, added, ways, rels, i;

        if (type === 'way') {

            // Update parentWays
            if (oldentity && entity) {
                removed = _.difference(oldentity.nodes, entity.nodes);
                added = _.difference(entity.nodes, oldentity.nodes);
            } else if (oldentity) {
                removed = oldentity.nodes;
                added = [];
            } else if (entity) {
                removed = [];
                added = entity.nodes;
            }
            for (i = 0; i < removed.length; i++) {
                parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
            }
            for (i = 0; i < added.length; i++) {
                ways = _.without(parentWays[added[i]], entity.id);
                ways.push(entity.id);
                parentWays[added[i]] = ways;
            }
        } else if (type === 'node') {

        } else if (type === 'relation') {

            // Update parentRels
            if (oldentity && entity) {
                removed = _.difference(oldentity.members, entity.members);
                added = _.difference(entity.members, oldentity);
            } else if (oldentity) {
                removed = oldentity.members;
                added = [];
            } else if (entity) {
                removed = [];
                added = entity.members;
            }
            for (i = 0; i < removed.length; i++) {
                parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
            }
            for (i = 0; i < added.length; i++) {
                rels = _.without(parentRels[added[i].id], entity.id);
                rels.push(entity.id);
                parentRels[added[i].id] = rels;
            }
        }
    },

    replace: function(entity) {
        return this.update(function () {
            this._updateCalculated(this.entities[entity.id], entity);
            this.entities[entity.id] = entity;
        });
    },

    remove: function(entity) {
        return this.update(function () {
            this._updateCalculated(entity, undefined);
            this.entities[entity.id] = undefined;
        });
    },

    update: function() {
        var graph = this.frozen ? iD.Graph(this, true) : this;

        for (var i = 0; i < arguments.length; i++) {
            arguments[i].call(graph, graph);
        }

        return this.frozen ? graph.freeze() : this;
    },

    freeze: function() {
        this.frozen = true;

        if (iD.debug) {
            Object.freeze(this.entities);
        }

        return this;
    },

    // get all objects that intersect an extent.
    intersects: function(extent) {
        var items = [];
        for (var i in this.entities) {
            var entity = this.entities[i];
            if (entity && entity.intersects(extent, this)) {
                items.push(entity);
            }
        }
        return items;
    },

    difference: function (graph) {
        var result = [],
            keys = Object.keys(this.entities),
            entity, oldentity, id, i;

        for (i = 0; i < keys.length; i++) {
            id = keys[i];
            entity = this.entities[id];
            oldentity = graph.entities[id];
            if (entity !== oldentity) {

                if (entity && entity.type === 'way' &&
                    oldentity && oldentity.type === 'way') {
                    result = result
                            .concat(_.difference(entity.nodes, oldentity.nodes))
                            .concat(_.difference(oldentity.nodes, entity.nodes));

                } else if (entity && entity.type === 'way') {
                    result = result.concat(entity.nodes);

                } else if (oldentity && oldentity.type === 'way') {
                    result = result.concat(oldentity.nodes);
                }

                result.push(id);
            }
        }

        keys = Object.keys(graph.entities);
        for (i = 0; i < keys.length; i++) {
            entity = graph.entities[id];
            if (entity && !this.entities.hasOwnProperty(id)) {
                result.push(id);
                if (entity.type === 'way') result = result.concat(entity.nodes);
            }
        }

        return result.sort();
    },

    modified: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (entity && base[id]) result.push(id);
        });
        return result;
    },

    created: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (entity && !base[id]) result.push(id);
        });
        return result;
    },

    deleted: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (!entity && base[id]) result.push(id);
        });
        return result;
    }
};
<commit_msg>Fix difference<commit_after>iD.Graph = function(other, mutable) {
    if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);

    if (other instanceof iD.Graph) {
        var base = other.base();
        this.entities = _.assign(Object.create(base.entities), other.entities);
        this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
        this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
        this.inherited = true;

    } else {
        if (_.isArray(other)) {
            var entities = {};
            for (var i = 0; i < other.length; i++) {
                entities[other[i].id] = other[i];
            }
            other = entities;
        }
        this.entities = Object.create({});
        this._parentWays = Object.create({});
        this._parentRels = Object.create({});
        this.rebase(other || {});
    }

    this.transients = {};
    this._childNodes = {};

    if (!mutable) {
        this.freeze();
    }
};

iD.Graph.prototype = {
    entity: function(id) {
        return this.entities[id];
    },

    transient: function(entity, key, fn) {
        var id = entity.id,
            transients = this.transients[id] ||
            (this.transients[id] = {});

        if (transients[key] !== undefined) {
            return transients[key];
        }

        return transients[key] = fn.call(entity);
    },

    parentWays: function(entity) {
        return _.map(this._parentWays[entity.id], _.bind(this.entity, this));
    },

    isPoi: function(entity) {
        return this.parentWays(entity).length === 0;
    },

    parentRelations: function(entity) {
        return _.map(this._parentRels[entity.id], _.bind(this.entity, this));
        var ent, id, parents;

        return this._parentRels[entity.id] || [];
    },

    childNodes: function(entity) {
        if (this._childNodes[entity.id])
            return this._childNodes[entity.id];

        var nodes = [];
        for (var i = 0, l = entity.nodes.length; i < l; i++) {
            nodes[i] = this.entity(entity.nodes[i]);
        }

        return (this._childNodes[entity.id] = nodes);
    },

    base: function() {
        return {
            'entities': iD.util.getPrototypeOf(this.entities),
            'parentWays': iD.util.getPrototypeOf(this._parentWays),
            'parentRels': iD.util.getPrototypeOf(this._parentRels)
        };
    },

    // Unlike other graph methods, rebase mutates in place. This is because it
    // is used only during the history operation that merges newly downloaded
    // data into each state. To external consumers, it should appear as if the
    // graph always contained the newly downloaded data.
    rebase: function(entities) {
        var i, keys;
        // Merging of data only needed if graph is the base graph
        if (!this.inherited) {
            _.defaults(this.base().entities, entities);
            for (i in entities) {
                this._updateCalculated(undefined, entities[i], this.base().parentWays, this.base().parentRels);
            }
        }

        keys = Object.keys(this._parentWays);
        for (i = 0; i < keys.length; i++) {
            this._parentWays[keys[i]] = _.unique((this._parentWays[keys[i]] || [])
                    .concat(this.base().parentWays[keys[i]] || []));
        }

        keys = Object.keys(this._parentRels);
        for (i = 0; i < keys.length; i++) {
            this._parentRels[keys[i]] = _.unique((this._parentRels[keys[i]] || [])
                    .concat(this.base().parentRels[keys[i]] || []));
        }
    },

    // Updates calculated properties (parentWays, parentRels) for the specified change
    _updateCalculated: function(oldentity, entity, parentWays, parentRels) {

        parentWays = parentWays || this._parentWays;
        parentRels = parentRels || this._parentRels;

        var type = entity && entity.type || oldentity && oldentity.type,
            removed, added, ways, rels, i;

        if (type === 'way') {

            // Update parentWays
            if (oldentity && entity) {
                removed = _.difference(oldentity.nodes, entity.nodes);
                added = _.difference(entity.nodes, oldentity.nodes);
            } else if (oldentity) {
                removed = oldentity.nodes;
                added = [];
            } else if (entity) {
                removed = [];
                added = entity.nodes;
            }
            for (i = 0; i < removed.length; i++) {
                parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
            }
            for (i = 0; i < added.length; i++) {
                ways = _.without(parentWays[added[i]], entity.id);
                ways.push(entity.id);
                parentWays[added[i]] = ways;
            }
        } else if (type === 'node') {

        } else if (type === 'relation') {

            // Update parentRels
            if (oldentity && entity) {
                removed = _.difference(oldentity.members, entity.members);
                added = _.difference(entity.members, oldentity);
            } else if (oldentity) {
                removed = oldentity.members;
                added = [];
            } else if (entity) {
                removed = [];
                added = entity.members;
            }
            for (i = 0; i < removed.length; i++) {
                parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
            }
            for (i = 0; i < added.length; i++) {
                rels = _.without(parentRels[added[i].id], entity.id);
                rels.push(entity.id);
                parentRels[added[i].id] = rels;
            }
        }
    },

    replace: function(entity) {
        return this.update(function () {
            this._updateCalculated(this.entities[entity.id], entity);
            this.entities[entity.id] = entity;
        });
    },

    remove: function(entity) {
        return this.update(function () {
            this._updateCalculated(entity, undefined);
            this.entities[entity.id] = undefined;
        });
    },

    update: function() {
        var graph = this.frozen ? iD.Graph(this, true) : this;

        for (var i = 0; i < arguments.length; i++) {
            arguments[i].call(graph, graph);
        }

        return this.frozen ? graph.freeze() : this;
    },

    freeze: function() {
        this.frozen = true;

        if (iD.debug) {
            Object.freeze(this.entities);
        }

        return this;
    },

    // get all objects that intersect an extent.
    intersects: function(extent) {
        var items = [];
        for (var i in this.entities) {
            var entity = this.entities[i];
            if (entity && entity.intersects(extent, this)) {
                items.push(entity);
            }
        }
        return items;
    },

    difference: function (graph) {
        var result = [],
            keys = Object.keys(this.entities),
            entity, oldentity, id, i;

        for (i = 0; i < keys.length; i++) {
            id = keys[i];
            entity = this.entities[id];
            oldentity = graph.entities[id];
            if (entity !== oldentity) {

                if (entity && entity.type === 'way' &&
                    oldentity && oldentity.type === 'way') {
                    result = result
                            .concat(_.difference(entity.nodes, oldentity.nodes))
                            .concat(_.difference(oldentity.nodes, entity.nodes));

                } else if (entity && entity.type === 'way') {
                    result = result.concat(entity.nodes);

                } else if (oldentity && oldentity.type === 'way') {
                    result = result.concat(oldentity.nodes);
                }

                result.push(id);
            }
        }

        keys = Object.keys(graph.entities);
        for (i = 0; i < keys.length; i++) {
            id = keys[i];
            entity = graph.entities[id];
            if (entity && !this.entities.hasOwnProperty(id)) {
                result.push(id);
                if (entity.type === 'way') result = result.concat(entity.nodes);
            }
        }

        return result.sort();
    },

    modified: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (entity && base[id]) result.push(id);
        });
        return result;
    },

    created: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (entity && !base[id]) result.push(id);
        });
        return result;
    },

    deleted: function() {
        var result = [], base = this.base().entities;
        _.each(this.entities, function(entity, id) {
            if (!entity && base[id]) result.push(id);
        });
        return result;
    }
};
<|endoftext|>


<commit_before>import React from 'react'
import Page, {mapDispatchToProps, jumpToTop, propTypes as pagePropTypes} from 'components/Page'
import * as yup from 'yup'

import { Formik, Form, Field } from 'formik'
import * as FieldHelper from 'components/FieldHelper'

import Breadcrumbs from 'components/Breadcrumbs'
import {Grid, Col, Row, Alert, Button, Checkbox} from 'react-bootstrap'
import Autocomplete from 'components/Autocomplete'
import LinkTo from 'components/LinkTo'
import moment from 'moment'
import Messages from 'components/Messages'

import Settings from 'Settings'
import {Person} from 'models'

import API from 'api'

import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'

class MergePeople extends Page {

	static propTypes = {...pagePropTypes}

	state = {
		success: null,
		error: null,
	}
	yupSchema = yup.object().shape({
		loser: yup.object().nullable().default({})
			// eslint-disable-next-line no-template-curly-in-string
			.test('required-objects', 'You must select a ${path}', value => value && value.uuid),
		winner: yup.object().nullable().default({})
			// eslint-disable-next-line no-template-curly-in-string
			.test('required-objectd', 'You must select a ${path}', value => value && value.uuid)
			.test(
				'not-equals-loser',
				'You selected the same person twice!',
				function(value) {
					const l = this.resolve(yup.ref('loser'))
					return value && value.uuid && l && l.uuid ? (value.uuid !== l.uuid) : true
				}
			)
			.test(
				'equal-roles',
				`You can only merge people of the same Role (i.e. ${Settings.fields.advisor.person.name}/${Settings.fields.principal.person.name})`,
				function(value) {
					const l = this.resolve(yup.ref('loser'))
					return value && value.role && l && l.role ? (value.role === l.role) : true
				}
			)
	})

	render() {
		const personFields = `uuid, name, emailAddress, domainUsername, createdAt, role, status, rank,
			position { uuid, name, organization { uuid, shortName, longName, identificationCode }},
			authoredReports(pageNum:0,pageSize:1) { totalCount }
			attendedReports(pageNum:0,pageSize:1) { totalCount }`

		return (

				<Breadcrumbs items={[['Merge People Tool', '/admin/mergePeople']]} />
				<Messages error={this.state.error} success={this.state.success} />

Merge People Tool

				<Alert bsStyle="warning">

Important: Select the two duplicative people below. The loser account will
					be deleted and all reports will be transferred over to the winner.

				</Alert>
				<Formik
					enableReinitialize={true}
					onSubmit={this.onSubmit}
					validationSchema={this.yupSchema}
					isInitialValid={() => this.yupSchema.isValidSync({})}
					initialValues={{loser: {}, winner: {}, copyPosition: false}}
				>
				{({
					isSubmitting,
					isValid,
					setFieldValue,
					setFieldTouched,
					values,
					submitForm
				}) => {
					const { loser, winner } = values
					return <Form>
						<Grid fluid>
							<Row>
								<Col md={6}>
									<Row>
										<Field
											name="loser"
											component={FieldHelper.renderSpecialField}
											vertical={true}
											onChange={value => {
												setFieldValue('loser', value)
												setFieldTouched('loser')  //onBlur doesn't work when selecting an option
												}
											}
											widget={
												<Autocomplete
													valueKey="name"
													placeholder="Select the duplicate person"
													objectType={Person}
													fields={personFields}
													template={person =>
														<LinkTo person={person} isLink={false} />
													}
												/>
											}
										/>
									</Row>
									<Row>
										{loser.uuid &&
											<fieldset>{this.showPersonDetails(new Person(loser))}</fieldset>
										}
									</Row>
								</Col>
								<Col md={6}>
									<Row>
										<Field
											name="winner"
											component={FieldHelper.renderSpecialField}
											vertical={true}
											onChange={value => {
												setFieldValue('winner', value)
												setFieldTouched('winner')  //onBlur doesn't work when selecting an option
												}
											}
											widget={
												<Autocomplete
													valueKey="name"
													placeholder="Select the OTHER duplicate person"
													objectType={Person}
													fields={personFields}
													template={person =>
														<LinkTo person={person} isLink={false} />
													}
												/>
											}
										/>
									</Row>
									<Row>
										{winner.uuid &&
											<fieldset>{this.showPersonDetails(new Person(winner))}</fieldset>
										}
									</Row>
								</Col>
							</Row>
							<Row>
								<Col md={12} >
									{loser.position && !winner.position &&
										<Field
											name="copyPosition"
											component={FieldHelper.renderSpecialField}
											label={null}
											widget={
												<Checkbox
													inline
													checked={values.copyPosition}
												>
												Set position on winner to {loser.position.name}
												</Checkbox>
											}
										/>
									}
									{loser.position && winner.position &&
										<Alert bsStyle="danger">
											Danger: Position on Loser ({loser.position.name}) will be left unfilled
										</Alert>
									}
								</Col>
							</Row>
							<Row>
								<Col md={12}>
									<Button bsStyle="primary" bsSize="large" block onClick={submitForm} disabled={isSubmitting || !isValid}>
										Merge People
									</Button>
								</Col>
							</Row>
						</Grid>
					</Form>
				}}
				</Formik>

		)
	}

	showPersonDetails = (person) => {
		return <React.Fragment>
			<Field
				name="uuid"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.uuid}
				vertical={true}
			/>
			<Field
				name="name"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.name}
				vertical={true}
			/>
			<Field
				name="status"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.humanNameOfStatus()}
				vertical={true}
			/>
			<Field
				name="role"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.humanNameOfRole()}
				vertical={true}
			/>
			<Field
				name="rank"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.rank}
				vertical={true}
			/>
			<Field
				name="emailAddress"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.emailAddress}
				vertical={true}
			/>
			<Field
				name="domainUsername"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.domainUsername}
				vertical={true}
			/>
			<Field
				name="createdAt"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.createdAt && moment(person.createdAt).format("DD MMM YYYY HH:mm:ss")}
				vertical={true}
			/>
			<Field
				name="position"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.position && <LinkTo position={person.position} />}
				vertical={true}
			/>
			<Field
				name="organization"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.position && <LinkTo organization={person.position.organization} />}
				vertical={true}
			/>
			<Field
				name="numReports"
				label="Number of Reports Written"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.authoredReports && person.authoredReports.totalCount}
				vertical={true}
			/>
			<Field
				name="numReportsIn"
				label="Number of Reports Attended"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.attendedReports && person.attendedReports.totalCount}
				vertical={true}
			/>
		</React.Fragment>
	}

	onSubmit = (values, form) => {
		return this.save(values, form)
			.then(response => this.onSubmitSuccess(response, values, form))
			.catch(error => {
				this.setState({success: null, error: error})
				jumpToTop()
				console.error(error)
			})
	}

	onSubmitSuccess = (response, values, form) => {
		if (response.mergePeople) {
			this.props.history.push({
				pathname: Person.pathFor(values.winner),
				state: {success: 'People merged'}
			})
		}
	}

	save = (values, form) => {
		const { winner, loser, copyPosition } = values
		const operation = 'mergePeople'
		const graphql = operation + '(winnerUuid: $winnerUuid, loserUuid: $loserUuid, copyPosition: $copyPosition)'
		const variables = {
				winnerUuid: winner.uuid,
				loserUuid: loser.uuid,
				copyPosition: copyPosition
		}
		const variableDef = '($winnerUuid: String!, $loserUuid: String!, $copyPosition: Boolean!)'
		return API.mutation(graphql, variables, variableDef)
	}

}

export default connect(null, mapDispatchToProps)(withRouter(MergePeople))
<commit_msg>NCI-Agency/anet#917: Change yup test name in mergePeople<commit_after>import React from 'react'
import Page, {mapDispatchToProps, jumpToTop, propTypes as pagePropTypes} from 'components/Page'
import * as yup from 'yup'

import { Formik, Form, Field } from 'formik'
import * as FieldHelper from 'components/FieldHelper'

import Breadcrumbs from 'components/Breadcrumbs'
import {Grid, Col, Row, Alert, Button, Checkbox} from 'react-bootstrap'
import Autocomplete from 'components/Autocomplete'
import LinkTo from 'components/LinkTo'
import moment from 'moment'
import Messages from 'components/Messages'

import Settings from 'Settings'
import {Person} from 'models'

import API from 'api'

import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'

class MergePeople extends Page {

	static propTypes = {...pagePropTypes}

	state = {
		success: null,
		error: null,
	}
	yupSchema = yup.object().shape({
		loser: yup.object().nullable().default({})
			// eslint-disable-next-line no-template-curly-in-string
			.test('required-object', 'You must select a ${path}', value => value && value.uuid),
		winner: yup.object().nullable().default({})
			// eslint-disable-next-line no-template-curly-in-string
			.test('required-object', 'You must select a ${path}', value => value && value.uuid)
			.test(
				'not-equals-loser',
				'You selected the same person twice!',
				function(value) {
					const l = this.resolve(yup.ref('loser'))
					return value && value.uuid && l && l.uuid ? (value.uuid !== l.uuid) : true
				}
			)
			.test(
				'equal-roles',
				`You can only merge people of the same Role (i.e. ${Settings.fields.advisor.person.name}/${Settings.fields.principal.person.name})`,
				function(value) {
					const l = this.resolve(yup.ref('loser'))
					return value && value.role && l && l.role ? (value.role === l.role) : true
				}
			)
	})

	render() {
		const personFields = `uuid, name, emailAddress, domainUsername, createdAt, role, status, rank,
			position { uuid, name, organization { uuid, shortName, longName, identificationCode }},
			authoredReports(pageNum:0,pageSize:1) { totalCount }
			attendedReports(pageNum:0,pageSize:1) { totalCount }`

		return (

				<Breadcrumbs items={[['Merge People Tool', '/admin/mergePeople']]} />
				<Messages error={this.state.error} success={this.state.success} />

Merge People Tool

				<Alert bsStyle="warning">

Important: Select the two duplicative people below. The loser account will
					be deleted and all reports will be transferred over to the winner.

				</Alert>
				<Formik
					enableReinitialize={true}
					onSubmit={this.onSubmit}
					validationSchema={this.yupSchema}
					isInitialValid={() => this.yupSchema.isValidSync({})}
					initialValues={{loser: {}, winner: {}, copyPosition: false}}
				>
				{({
					isSubmitting,
					isValid,
					setFieldValue,
					setFieldTouched,
					values,
					submitForm
				}) => {
					const { loser, winner } = values
					return <Form>
						<Grid fluid>
							<Row>
								<Col md={6}>
									<Row>
										<Field
											name="loser"
											component={FieldHelper.renderSpecialField}
											vertical={true}
											onChange={value => {
												setFieldValue('loser', value)
												setFieldTouched('loser')  //onBlur doesn't work when selecting an option
												}
											}
											widget={
												<Autocomplete
													valueKey="name"
													placeholder="Select the duplicate person"
													objectType={Person}
													fields={personFields}
													template={person =>
														<LinkTo person={person} isLink={false} />
													}
												/>
											}
										/>
									</Row>
									<Row>
										{loser.uuid &&
											<fieldset>{this.showPersonDetails(new Person(loser))}</fieldset>
										}
									</Row>
								</Col>
								<Col md={6}>
									<Row>
										<Field
											name="winner"
											component={FieldHelper.renderSpecialField}
											vertical={true}
											onChange={value => {
												setFieldValue('winner', value)
												setFieldTouched('winner')  //onBlur doesn't work when selecting an option
												}
											}
											widget={
												<Autocomplete
													valueKey="name"
													placeholder="Select the OTHER duplicate person"
													objectType={Person}
													fields={personFields}
													template={person =>
														<LinkTo person={person} isLink={false} />
													}
												/>
											}
										/>
									</Row>
									<Row>
										{winner.uuid &&
											<fieldset>{this.showPersonDetails(new Person(winner))}</fieldset>
										}
									</Row>
								</Col>
							</Row>
							<Row>
								<Col md={12} >
									{loser.position && !winner.position &&
										<Field
											name="copyPosition"
											component={FieldHelper.renderSpecialField}
											label={null}
											widget={
												<Checkbox
													inline
													checked={values.copyPosition}
												>
												Set position on winner to {loser.position.name}
												</Checkbox>
											}
										/>
									}
									{loser.position && winner.position &&
										<Alert bsStyle="danger">
											Danger: Position on Loser ({loser.position.name}) will be left unfilled
										</Alert>
									}
								</Col>
							</Row>
							<Row>
								<Col md={12}>
									<Button bsStyle="primary" bsSize="large" block onClick={submitForm} disabled={isSubmitting || !isValid}>
										Merge People
									</Button>
								</Col>
							</Row>
						</Grid>
					</Form>
				}}
				</Formik>

		)
	}

	showPersonDetails = (person) => {
		return <React.Fragment>
			<Field
				name="uuid"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.uuid}
				vertical={true}
			/>
			<Field
				name="name"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.name}
				vertical={true}
			/>
			<Field
				name="status"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.humanNameOfStatus()}
				vertical={true}
			/>
			<Field
				name="role"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.humanNameOfRole()}
				vertical={true}
			/>
			<Field
				name="rank"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.rank}
				vertical={true}
			/>
			<Field
				name="emailAddress"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.emailAddress}
				vertical={true}
			/>
			<Field
				name="domainUsername"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.domainUsername}
				vertical={true}
			/>
			<Field
				name="createdAt"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.createdAt && moment(person.createdAt).format("DD MMM YYYY HH:mm:ss")}
				vertical={true}
			/>
			<Field
				name="position"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.position && <LinkTo position={person.position} />}
				vertical={true}
			/>
			<Field
				name="organization"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.position && <LinkTo organization={person.position.organization} />}
				vertical={true}
			/>
			<Field
				name="numReports"
				label="Number of Reports Written"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.authoredReports && person.authoredReports.totalCount}
				vertical={true}
			/>
			<Field
				name="numReportsIn"
				label="Number of Reports Attended"
				component={FieldHelper.renderReadonlyField}
				humanValue={person.attendedReports && person.attendedReports.totalCount}
				vertical={true}
			/>
		</React.Fragment>
	}

	onSubmit = (values, form) => {
		return this.save(values, form)
			.then(response => this.onSubmitSuccess(response, values, form))
			.catch(error => {
				this.setState({success: null, error: error})
				jumpToTop()
				console.error(error)
			})
	}

	onSubmitSuccess = (response, values, form) => {
		if (response.mergePeople) {
			this.props.history.push({
				pathname: Person.pathFor(values.winner),
				state: {success: 'People merged'}
			})
		}
	}

	save = (values, form) => {
		const { winner, loser, copyPosition } = values
		const operation = 'mergePeople'
		const graphql = operation + '(winnerUuid: $winnerUuid, loserUuid: $loserUuid, copyPosition: $copyPosition)'
		const variables = {
				winnerUuid: winner.uuid,
				loserUuid: loser.uuid,
				copyPosition: copyPosition
		}
		const variableDef = '($winnerUuid: String!, $loserUuid: String!, $copyPosition: Boolean!)'
		return API.mutation(graphql, variables, variableDef)
	}

}

export default connect(null, mapDispatchToProps)(withRouter(MergePeople))
<|endoftext|>


<commit_before>Template.add_post.events({
    'submit .add_post_form': function(){
        var title = event.target.title.value;
        var body = event.target.body.value;

        // Insert the post
        Posts.insert({
            title: title,
            body: body
        });

        FlashMessages.sendSuccess('Post has been successfully added!');
        Router.go('/admin/posts');

        // Prevent submit
        return false;
    }
});
<commit_msg>Edit & Remove Posts<commit_after>Template.add_post.events({
    'submit .add_post_form': function(){
        var title = event.target.title.value;
        var body = event.target.body.value;

        // Insert the post
        Posts.insert({
            title: title,
            body: body
        });

        FlashMessages.sendSuccess('Post successfully added!');
        Router.go('/admin/posts');

        // Prevent submit
        return false;
    }
});

Template.edit_post.events({
    'submit .edit_post_form': function(event) {
        var title = event.target.title.value;
        var body = event.target.body.value;

        // Update the post
        Posts.update({
            _id: this._id
            }, {
                $set: {title: title, body: body}
        });

        FlashMessages.sendSuccess('Post successfully updated!');
        Router.go('/admin/posts');

        // Prevent submit
        return false;
    }
});

Template.list_posts.events({
    'click .delete_post': function(event) {
        if (confirm('Do you really want to delete "' + this.title + '" post?')) {
            Posts.remove(this._id);
            FlashMessages.sendSuccess('Post successfully deleted!');

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


<commit_before>/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Externs file for OpenSocial shindig libraries.
 * Note this may not be comprehensive.
 *
 * @see http://incubator.apache.org/shindig/shindig-1.1.x/shindig-features/jsdoc
 * @externs
 */

// Root namespace for shindig related functionality.
var shindig = {};

/**
 * Implements a safer random() method that is seeded from
 * screen width/height and (presumably random/unguessable) mouse
 * movement, in an effort to create a better seed for random().
 * @return {number} The random number.
 */
shindig.random = function() {};

/**
 * Implements a SHA1 hasher.
 * @return {Object} SHA1 hasher object.
 */
shindig.sha1 = function() {};
<commit_msg><commit_after>/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Externs file for OpenSocial shindig libraries.
 * Note this may not be comprehensive.
 *
 * @see http://incubator.apache.org/shindig/shindig-1.1.x/shindig-features/jsdoc
 * @externs
 */

// Root namespace for shindig related functionality.
var shindig = {};

/**
 * Implements a safer random() method that is seeded from
 * screen width/height and (presumably random/unguessable) mouse
 * movement, in an effort to create a better seed for random().
 * @return {number} The random number.
 */
shindig.random = function() {};

/**
 * Implements a SHA1 hasher.
 * @return {{reset: function(), update:
 * function(Array.<number>|string,number=), digest:
 * function():Array.<number>, digestString: function():string}} SHA1
 * hasher object. Methods of the returned object are: reset() which
 * resets the internal accumulator, update(bytes, opt_length) which
 * adds a byte array or string to the internal accumulator (or
 * optionally just a prefix of length opt_length), digest() which
 * returns a finalized hash as an array of 20 byte values, and
 * digestString() which returns a hex-encoded string containing a
 * finalized hash.
 */
shindig.sha1 = function() {};
<|endoftext|>


<commit_before>/*
	FlexNav.js 0.8

	Copyright 2013, Jason Weaver http://jasonweaver.name
	Released under http://unlicense.org/

//
*/

(function() {
  $.fn.flexNav = function(options) {
    var $nav, breakpoint, isDragging, nav_open, resizer, settings;
    settings = $.extend({
      'animationSpeed': 100
    }, options);
    $nav = $(this);
    nav_open = false;
    isDragging = false;
    $nav.find("li").each(function() {
      if ($(this).has("ul").length) {
        return $(this).addClass("item-with-ul").find("ul").hide();
      }
    });
    if ($nav.data('breakpoint')) {
      breakpoint = $nav.data('breakpoint');
    }
    resizer = function() {
      if ($(window).width() <= breakpoint) {
        $nav.removeClass("lg-screen").addClass("sm-screen");
        $('.one-page li a').on('click', function() {
          return $nav.removeClass('show');
        });
        return $('.item-with-ul').off();
      } else {
        $nav.removeClass("sm-screen").addClass("lg-screen");
        $nav.removeClass('show');
        return $('.item-with-ul').on('mouseenter', function() {
          return $(this).find('>ul').addClass('show').stop(true, true).slideDown(settings.animationSpeed);
        }).on('mouseleave', function() {
          return $(this).find('>ul').removeClass('show').stop(true, true).slideUp(settings.animationSpeed);
        });
      }
    };
    $('.item-with-ul, .menu-button').append('▼');
    $('.menu-button, .menu-button .touch-button').on('touchstart mousedown', function(e) {
      e.preventDefault();
      e.stopPropagation();
      console.log(isDragging);
      return $(this).on('touchmove mousemove', function(e) {
        var msg;
        msg = e.pageX;
        isDragging = true;
        return $(window).off("touchmove mousemove");
      });
    }).on('touchend mouseup', function(e) {
      var $parent;
      e.preventDefault();
      e.stopPropagation();
      isDragging = false;
      $parent = $(this).parent();
      if (isDragging === false) {
        console.log('clicked');
      }
      if (nav_open === false) {
        $nav.addClass('show');
        return nav_open = true;
      } else if (nav_open === true) {
        $nav.removeClass('show');
        return nav_open = false;
      }
    });
    $('.touch-button').on('touchstart mousedown', function(e) {
      e.stopPropagation();
      e.preventDefault();
      return $(this).on('touchmove mousemove', function(e) {
        isDragging = true;
        return $(window).off("touchmove mousemove");
      });
    }).on('touchend mouseup', function(e) {
      var $sub;
      e.preventDefault();
      e.stopPropagation();
      $sub = $(this).parent('.item-with-ul').find('>ul');
      if ($nav.hasClass('lg-screen') === true) {
        $(this).parent('.item-with-ul').siblings().find('ul.show').removeClass('show').hide();
      }
      if ($sub.hasClass('show') === true) {
        return $sub.removeClass('show').slideUp(settings.animationSpeed);
      } else if ($sub.hasClass('show') === false) {
        return $sub.addClass('show').slideDown(settings.animationSpeed);
      }
    });
    $('.item-with-ul *').focus(function() {
      $(this).parent('.item-with-ul').parent().find(".open").not(this).removeClass("open").hide();
      return $(this).parent('.item-with-ul').find('>ul').addClass("open").show();
    });
    resizer();
    return $(window).on('resize', resizer);
  };

}).call(this);
<commit_msg>Add hoverIntent support <commit_after>/*
	FlexNav.js 0.8

	Copyright 2013, Jason Weaver http://jasonweaver.name
	Released under http://unlicense.org/

//
*/

(function() {
  $.fn.flexNav = function(options) {
    var $nav, breakpoint, isDragging, nav_open, resizer, settings;
    settings = $.extend({
      'animationSpeed': 100
    }, options);
    $nav = $(this);
    nav_open = false;
    isDragging = false;
    $nav.find("li").each(function() {
      if ($(this).has("ul").length) {
        return $(this).addClass("item-with-ul").find("ul").hide();
      }
    });
    if ($nav.data('breakpoint')) {
      breakpoint = $nav.data('breakpoint');
    }
    resizer = function() {
      if ($(window).width() <= breakpoint) {
        $nav.removeClass("lg-screen").addClass("sm-screen");
        $('.one-page li a').on('click', function() {
          return $nav.removeClass('show');
        });
        return $('.item-with-ul').off();
      } else {
        $nav.removeClass("sm-screen").addClass("lg-screen");
        $nav.removeClass('show');
         return $('.item-with-ul').hoverIntent({
	            over: showMenu,
	            out: resetMenu,
	            timeout: 100
	        });
      }
    };
    $('.item-with-ul, .menu-button').append('▼');
    $('.menu-button, .menu-button .touch-button').on('touchstart mousedown', function(e) {
      e.preventDefault();
      e.stopPropagation();
      console.log(isDragging);
      return $(this).on('touchmove mousemove', function(e) {
        var msg;
        msg = e.pageX;
        isDragging = true;
        return $(window).off("touchmove mousemove");
      });
    }).on('touchend mouseup', function(e) {
      var $parent;
      e.preventDefault();
      e.stopPropagation();
      isDragging = false;
      $parent = $(this).parent();
      if (isDragging === false) {
        console.log('clicked');
      }
      if (nav_open === false) {
        $nav.addClass('show');
        return nav_open = true;
      } else if (nav_open === true) {
        $nav.removeClass('show');
        return nav_open = false;
      }
    });
    $('.touch-button').on('touchstart mousedown', function(e) {
      e.stopPropagation();
      e.preventDefault();
      return $(this).on('touchmove mousemove', function(e) {
        isDragging = true;
        return $(window).off("touchmove mousemove");
      });
    }).on('touchend mouseup', function(e) {
      var $sub;
      e.preventDefault();
      e.stopPropagation();
      $sub = $(this).parent('.item-with-ul').find('>ul');
      if ($nav.hasClass('lg-screen') === true) {
        $(this).parent('.item-with-ul').siblings().find('ul.show').removeClass('show').hide();
      }
      if ($sub.hasClass('show') === true) {
        return $sub.removeClass('show').slideUp(settings.animationSpeed);
      } else if ($sub.hasClass('show') === false) {
        return $sub.addClass('show').slideDown(settings.animationSpeed);
      }
    });
    $('.item-with-ul *').focus(function() {
      $(this).parent('.item-with-ul').parent().find(".open").not(this).removeClass("open").hide();
      return $(this).parent('.item-with-ul').find('>ul').addClass("open").show();
    });
    resizer();
    return $(window).on('resize', resizer);
  };

}).call(this);

function showMenu(){
    $(this).find('> ul').fadeIn(100);
}
function resetMenu(){
    $(this).find('> ul').fadeOut(100);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview Definitions for objects in the syncrhonous File API, File
 * Writer API, and File System API. Details of the API are at:
 * http://www.w3.org/TR/FileAPI/
 * http://www.w3.org/TR/file-writer-api/
 * http://www.w3.org/TR/file-system-api/
 *
 * @externs
 */

/**
 * @see http://www.w3.org/TR/file-writer-api/#idl-def-FileWriterSync
 * @constructor
 */
function FileWriterSync() {}

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-position
 * @type {number}
 * @const
 */
FileWriterSync.prototype.position;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-length
 * @type {number}
 * @const
 */
FileWriterSync.prototype.length;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-write
 * @param {!Blob} blob
 */
FileWriterSync.prototype.write = function(blob) {};

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-seek
 * @param {number} offset
 */
FileWriterSync.prototype.seek = function(offset) {};

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-truncate
 * @param {number} size
 */
FileWriterSync.prototype.truncate = function(size) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#FileReaderSyncSync
 * @constructor
 */
function FileReaderSync() {}

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsArrayBufferSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsArrayBuffer = function(blob) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsBinaryStringSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsBinaryString = function(blob) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsTextSync
 * @param {!Blob} blob
 * @param {string=} encoding
 */
FileReaderSync.prototype.readAsText = function(blob, encoding) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsDataURLSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsDataURL = function(blob) {};

/**
 * LocalFileSystemSync interface, implemented by WorkerGlobalScope.
 * @see http://www.w3.org/TR/file-system-api/#idl-def-LocalFileSystemSync
 * @constructor
 */
function LocalFileSystemSync() {}

/**
 * @see http://www.w3.org/TR/file-system-api/
 *     #the-synchronous-filesystem-interface
 * @constructor
 */
function FileSystemSync() {}

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileSystemSync-name
 * @type {string}
 * @const
 */
FileSystemSync.prototype.name;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileSystemSync-root
 * @type {!DirectoryEntrySync}
 * @const
 */
FileSystemSync.prototype.root;

/**
 * @see http://www.w3.org/TR/file-system-api/#the-entrysync-interface
 * @constructor
 */
function EntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-isFile
 * @type {boolean}
 * @const
 */
EntrySync.prototype.isFile;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-isDirectory
 * @type {boolean}
 * @const
 */
EntrySync.prototype.isDirectory;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-name
 * @type {string}
 * @const
 */
EntrySync.prototype.name;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-fullPath
 * @type {string}
 * @const
 */
EntrySync.prototype.fullPath;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-filesystem
 * @type {!FileSystemSync}
 * @const
 */
EntrySync.prototype.filesystem;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-moveTo
 * @param {!DirectoryEntrySync} parent
 * @param {string=} newName
 * @return {!EntrySync}
 */
EntrySync.prototype.moveTo = function(parent, newName) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-copyTo
 * @param {!DirectoryEntrySync} parent
 * @param {string=} newName
 * @return {!EntrySync}
 */
EntrySync.prototype.copyTo = function(parent, newName) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-toURL
 * @param {string=} mimeType
 * @return {string}
 */
EntrySync.prototype.toURL = function(mimeType) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-remove
 */
EntrySync.prototype.remove = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-getMetadata
 * @return {!Metadata}
 */
EntrySync.prototype.getMetadata = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-getParent
 * @return {!DirectoryEntrySync}
 */
EntrySync.prototype.getParent = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-directoryentrysync-interface
 * @constructor
 * @extends {EntrySync}
 */
function DirectoryEntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-createReader
 * @return {!DirectoryReaderSync}
 */
DirectoryEntrySync.prototype.createReader = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-getFile
 * @param {string} path
 * @param {Object=} options
 * @return {!FileEntrySync}
 */
DirectoryEntrySync.prototype.getFile = function(path, options) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-getDirectory
 * @param {string} path
 * @param {Object=} options
 * @return {!DirectoryEntrySync}
 */
DirectoryEntrySync.prototype.getDirectory = function(path, options) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-removeRecursively
 */
DirectoryEntrySync.prototype.removeRecursively = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-directoryreadersync-interface
 * @constructor
 */
function DirectoryReaderSync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryReaderSync-readEntries
 * @return {!Array.<!EntrySync>}
 */
DirectoryReaderSync.prototype.readEntries = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-fileentrysync-interface
 * @constructor
 * @extends {EntrySync}
 */
function FileEntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileEntrySync-createWriter
 * @return {!FileWriterSync}
 */
FileEntrySync.prototype.createWriter = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileEntrySync-file
 * @return {!File}
 */
FileEntrySync.prototype.file = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-fileexception-exception
 * @constructor
 */
function FileException() {}

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-NOT_FOUND_ERR
 * @type {number}
 */
FileException.prototype.NOT_FOUND_ERR = 1;

/** @type {number} */
FileException.NOT_FOUND_ERR = 1;

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-SECURITY_ERR
 * @type {number}
 */
FileException.prototype.SECURITY_ERR = 2;

/** @type {number} */
FileException.SECURITY_ERR = 2;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-ABORT_ERR
 * @type {number}
 */
FileException.prototype.ABORT_ERR = 3;

/** @type {number} */
FileException.ABORT_ERR = 3;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-NOT_READABLE_ERR
 * @type {number}
 */
FileException.prototype.NOT_READABLE_ERR = 4;

/** @type {number} */
FileException.NOT_READABLE_ERR = 4;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-ENCODING_ERR
 * @type {number}
 */
FileException.prototype.ENCODING_ERR = 5;

/** @type {number} */
FileException.ENCODING_ERR = 5;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-NO_MODIFICATION_ALLOWED_ERR
 * @type {number}
 */
FileException.prototype.NO_MODIFICATION_ALLOWED_ERR = 6;

/** @type {number} */
FileException.NO_MODIFICATION_ALLOWED_ERR = 6;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-INVALID_STATE_ERR
 * @type {number}
 */
FileException.prototype.INVALID_STATE_ERR = 7;

/** @type {number} */
FileException.INVALID_STATE_ERR = 7;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-SYNTAX_ERR
 * @type {number}
 */
FileException.prototype.SYNTAX_ERR = 8;

/** @type {number} */
FileException.SYNTAX_ERR = 8;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-INVALID_MODIFICATION_ERR
 * @type {number}
 */
FileException.prototype.INVALID_MODIFICATION_ERR = 9;

/** @type {number} */
FileException.INVALID_MODIFICATION_ERR = 9;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-QUOTA_EXCEEDED_ERR
 * @type {number}
 */
FileException.prototype.QUOTA_EXCEEDED_ERR = 10;

/** @type {number} */
FileException.QUOTA_EXCEEDED_ERR = 10;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-TYPE_MISMATCH_ERR
 * @type {number}
 */
FileException.prototype.TYPE_MISMATCH_ERR = 11;

/** @type {number} */
FileException.TYPE_MISMATCH_ERR = 11;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-PATH_EXISTS_ERR
 * @type {number}
 */
FileException.prototype.PATH_EXISTS_ERR = 12;

/** @type {number} */
FileException.PATH_EXISTS_ERR = 12;

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-code-exception
 * @type {number}
 */
FileException.prototype.code;
<commit_msg><commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview Definitions for objects in the syncrhonous File API, File
 * Writer API, and File System API. Details of the API are at:
 * http://www.w3.org/TR/FileAPI/
 * http://www.w3.org/TR/file-writer-api/
 * http://www.w3.org/TR/file-system-api/
 *
 * @externs
 */

/**
 * @see http://www.w3.org/TR/file-writer-api/#idl-def-FileWriterSync
 * @constructor
 */
function FileWriterSync() {}

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-position
 * @type {number}
 * @const
 */
FileWriterSync.prototype.position;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-length
 * @type {number}
 * @const
 */
FileWriterSync.prototype.length;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriter-write
 * @param {!Blob} blob
 */
FileWriterSync.prototype.write = function(blob) {};

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-seek
 * @param {number} offset
 */
FileWriterSync.prototype.seek = function(offset) {};

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileWriterSync-truncate
 * @param {number} size
 */
FileWriterSync.prototype.truncate = function(size) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#FileReaderSyncSync
 * @constructor
 */
function FileReaderSync() {}

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsArrayBufferSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsArrayBuffer = function(blob) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsBinaryStringSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsBinaryString = function(blob) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsTextSync
 * @param {!Blob} blob
 * @param {string=} encoding
 */
FileReaderSync.prototype.readAsText = function(blob, encoding) {};

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-readAsDataURLSync
 * @param {!Blob} blob
 */
FileReaderSync.prototype.readAsDataURL = function(blob) {};

/**
 * LocalFileSystemSync interface, implemented by WorkerGlobalScope.
 * @see http://www.w3.org/TR/file-system-api/#idl-def-LocalFileSystemSync
 * @constructor
 */
function LocalFileSystemSync() {}

/**
 * @see http://www.w3.org/TR/file-system-api/
 *     #the-synchronous-filesystem-interface
 * @constructor
 */
function FileSystemSync() {}

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileSystemSync-name
 * @type {string}
 * @const
 */
FileSystemSync.prototype.name;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileSystemSync-root
 * @type {!DirectoryEntrySync}
 * @const
 */
FileSystemSync.prototype.root;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystemSync-requestFileSystemSync-FileSystemSync-unsigned-short-type-unsigned-long-long-size
 * @param {number} type
 * @param {number} size
 * @return {!FileSystemSync}
 */
function requestFileSystemSync(type, size) {}

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-LocalFileSystemSync-requestFileSystemSync-FileSystemSync-unsigned-short-type-unsigned-long-long-size
 * @param {number} type
 * @param {number} size
 * @return {!FileSystemSync}
 */
function webkitRequestFileSystemSync(type, size) {}

/**
 * @see http://www.w3.org/TR/file-system-api/#the-entrysync-interface
 * @constructor
 */
function EntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-isFile
 * @type {boolean}
 * @const
 */
EntrySync.prototype.isFile;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-isDirectory
 * @type {boolean}
 * @const
 */
EntrySync.prototype.isDirectory;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-name
 * @type {string}
 * @const
 */
EntrySync.prototype.name;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-fullPath
 * @type {string}
 * @const
 */
EntrySync.prototype.fullPath;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-filesystem
 * @type {!FileSystemSync}
 * @const
 */
EntrySync.prototype.filesystem;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-moveTo
 * @param {!DirectoryEntrySync} parent
 * @param {string=} newName
 * @return {!EntrySync}
 */
EntrySync.prototype.moveTo = function(parent, newName) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-copyTo
 * @param {!DirectoryEntrySync} parent
 * @param {string=} newName
 * @return {!EntrySync}
 */
EntrySync.prototype.copyTo = function(parent, newName) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-toURL
 * @param {string=} mimeType
 * @return {string}
 */
EntrySync.prototype.toURL = function(mimeType) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-remove
 */
EntrySync.prototype.remove = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-getMetadata
 * @return {!Metadata}
 */
EntrySync.prototype.getMetadata = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-EntrySync-getParent
 * @return {!DirectoryEntrySync}
 */
EntrySync.prototype.getParent = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-directoryentrysync-interface
 * @constructor
 * @extends {EntrySync}
 */
function DirectoryEntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-createReader
 * @return {!DirectoryReaderSync}
 */
DirectoryEntrySync.prototype.createReader = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-getFile
 * @param {string} path
 * @param {Object=} options
 * @return {!FileEntrySync}
 */
DirectoryEntrySync.prototype.getFile = function(path, options) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-getDirectory
 * @param {string} path
 * @param {Object=} options
 * @return {!DirectoryEntrySync}
 */
DirectoryEntrySync.prototype.getDirectory = function(path, options) {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryEntrySync-removeRecursively
 */
DirectoryEntrySync.prototype.removeRecursively = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-directoryreadersync-interface
 * @constructor
 */
function DirectoryReaderSync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-DirectoryReaderSync-readEntries
 * @return {!Array.<!EntrySync>}
 */
DirectoryReaderSync.prototype.readEntries = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-fileentrysync-interface
 * @constructor
 * @extends {EntrySync}
 */
function FileEntrySync() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileEntrySync-createWriter
 * @return {!FileWriterSync}
 */
FileEntrySync.prototype.createWriter = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileEntrySync-file
 * @return {!File}
 */
FileEntrySync.prototype.file = function() {};

/**
 * @see http://www.w3.org/TR/file-system-api/#the-fileexception-exception
 * @constructor
 */
function FileException() {}

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-NOT_FOUND_ERR
 * @type {number}
 */
FileException.prototype.NOT_FOUND_ERR = 1;

/** @type {number} */
FileException.NOT_FOUND_ERR = 1;

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-SECURITY_ERR
 * @type {number}
 */
FileException.prototype.SECURITY_ERR = 2;

/** @type {number} */
FileException.SECURITY_ERR = 2;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-ABORT_ERR
 * @type {number}
 */
FileException.prototype.ABORT_ERR = 3;

/** @type {number} */
FileException.ABORT_ERR = 3;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-NOT_READABLE_ERR
 * @type {number}
 */
FileException.prototype.NOT_READABLE_ERR = 4;

/** @type {number} */
FileException.NOT_READABLE_ERR = 4;

/**
 * @see http://www.w3.org/TR/FileAPI/#widl-FileException-ENCODING_ERR
 * @type {number}
 */
FileException.prototype.ENCODING_ERR = 5;

/** @type {number} */
FileException.ENCODING_ERR = 5;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-NO_MODIFICATION_ALLOWED_ERR
 * @type {number}
 */
FileException.prototype.NO_MODIFICATION_ALLOWED_ERR = 6;

/** @type {number} */
FileException.NO_MODIFICATION_ALLOWED_ERR = 6;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-INVALID_STATE_ERR
 * @type {number}
 */
FileException.prototype.INVALID_STATE_ERR = 7;

/** @type {number} */
FileException.INVALID_STATE_ERR = 7;

/**
 * @see http://www.w3.org/TR/file-writer-api/#widl-FileException-SYNTAX_ERR
 * @type {number}
 */
FileException.prototype.SYNTAX_ERR = 8;

/** @type {number} */
FileException.SYNTAX_ERR = 8;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-INVALID_MODIFICATION_ERR
 * @type {number}
 */
FileException.prototype.INVALID_MODIFICATION_ERR = 9;

/** @type {number} */
FileException.INVALID_MODIFICATION_ERR = 9;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-QUOTA_EXCEEDED_ERR
 * @type {number}
 */
FileException.prototype.QUOTA_EXCEEDED_ERR = 10;

/** @type {number} */
FileException.QUOTA_EXCEEDED_ERR = 10;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-TYPE_MISMATCH_ERR
 * @type {number}
 */
FileException.prototype.TYPE_MISMATCH_ERR = 11;

/** @type {number} */
FileException.TYPE_MISMATCH_ERR = 11;

/**
 * @see http://www.w3.org/TR/file-system-api/#widl-FileException-PATH_EXISTS_ERR
 * @type {number}
 */
FileException.prototype.PATH_EXISTS_ERR = 12;

/** @type {number} */
FileException.PATH_EXISTS_ERR = 12;

/**
 * @see http://www.w3.org/TR/FileAPI/#dfn-code-exception
 * @type {number}
 */
FileException.prototype.code;
<|endoftext|>


<commit_before>/*! Imadaem v0.4.0 http://imadaem.penibelst.de/ */

(function ($, window) {
    "use strict";

    $.fn.imadaem = function(options) {
        var
            $elements = this,

            settings = $.extend({
                dataAttribute: "imadaem",
                timthumbPath: "/timthumb/timthumb.php",
                verticalRhythm: null,
                windowEvents: "resize orientationchange"
            }, options),

            getNativeLength = function (cssLength) {
                var density = window.devicePixelRatio || 1;
                return Math.round(cssLength * density);
            },

            lineHeight = function ($element) {
                var lh = parseFloat($element.css("line-height"));
                return isNaN(lh) ? 0 : lh;
            },

            adjustVerticalRhythm = function ($element, height) {
                if (settings.verticalRhythm === "line-height") {
                    var lh, l;
                    lh = lineHeight($element);
                    if (lh) {
                        l = Math.max(1, Math.round(height / lh));
                        height = lh * l;
                    }
                }
                return height;
            },

            getData = function ($element) {
                var data = $element.data(settings.dataAttribute);
                if ($.isPlainObject(data)) {
                    // ratio must be a number
                    data.ratio = parseFloat(data.ratio) || 0;
                    // ignore maxRatio if ratio is set
                    data.maxRatio = data.ratio ? 0 : parseFloat(data.maxRatio) || 0;
                    // gravity must be a combination of ["l", "r", "t", "b"]
                    data.gravity = data.gravity ? data.gravity.replace(/[^lrtb]/g, "").substr(0, 2) : "";
                } else {
                    data = {url: data};
                }
                return data;
            },

            scale = function () {
                var
                    $this,
                    data,
                    timthumbParams,
                    height,
                    minHeight,
                    width;

                $elements.each(function () {
                    $this = $(this);
                    data = getData($this);

                    width = $this.innerWidth();
                    height = $this.innerHeight();

                    if (data.ratio) {
                        height = Math.round(width / data.ratio);
                    } else if ($(data.heightGuide).length) {
                        height = $(data.heightGuide).innerHeight();
                    }

                    if (data.maxRatio) {
                        minHeight = Math.round(width / data.maxRatio);
                        height = Math.max(minHeight, height);
                    }

                    height = adjustVerticalRhythm($this, height);

                    // prevent blinking effects
                    $this.height(height);

                    timthumbParams = {
                        src: data.url || "",
                        a: data.gravity || "",
                        w: getNativeLength(width),
                        h: getNativeLength(height)
                    };

                    $this.attr("src", settings.timthumbPath + "?" + $.param(timthumbParams));
                });
            };

        $(window)
            .one("load", scale)
            .on(settings.windowEvents, scale);

        return this;
    };
})(jQuery, window);
<commit_msg>Improve data attribute checks<commit_after>/*! Imadaem v0.4.0 http://imadaem.penibelst.de/ */

(function ($, window) {
    "use strict";

    $.fn.imadaem = function(options) {
        var
            $elements = this,

            settings = $.extend({
                dataAttribute: "imadaem",
                timthumbPath: "/timthumb/timthumb.php",
                verticalRhythm: null,
                windowEvents: "resize orientationchange"
            }, options),

            getNativeLength = function (cssLength) {
                var density = window.devicePixelRatio || 1;
                return Math.round(cssLength * density);
            },

            lineHeight = function ($element) {
                var lh = parseFloat($element.css("line-height"));
                return isNaN(lh) ? 0 : lh;
            },

            adjustVerticalRhythm = function ($element, height) {
                if (settings.verticalRhythm === "line-height") {
                    var lh, l;
                    lh = lineHeight($element);
                    if (lh) {
                        l = Math.max(1, Math.round(height / lh));
                        height = lh * l;
                    }
                }
                return height;
            },

            getData = function ($element) {
                var data = $element.data(settings.dataAttribute);

                if (typeof data === "string") {
                    data = {url: data};
                } else if ($.isPlainObject(data)) {

                    // ratio must be a number
                    data.ratio = parseFloat(data.ratio) || 0;

                    // ignore maxRatio if ratio is set
                    data.maxRatio = data.ratio ? 0 : parseFloat(data.maxRatio) || 0;

                    // gravity must be a combination of ["l", "r", "t", "b"]
                    data.gravity = data.gravity ? data.gravity.replace(/[^lrtb]/g, "").substr(0, 2) : "";
                }
                return $.extend({
                    url: "",
                    gravity: "",
                    ratio: 0,
                    maxRatio: 0,
                    heightGuide: ""
                }, data);
            },

            scale = function () {
                var
                    $this,
                    data,
                    timthumbParams,
                    height,
                    minHeight,
                    width;

                $elements.each(function () {
                    $this = $(this);

                    data = getData($this);
                    if (!data.url) {
                        return;
                    }

                    width = $this.innerWidth();
                    height = $this.innerHeight();

                    if (data.ratio) {
                        height = Math.round(width / data.ratio);
                    } else if ($(data.heightGuide).length) {
                        height = $(data.heightGuide).innerHeight();
                    }

                    if (data.maxRatio) {
                        minHeight = Math.round(width / data.maxRatio);
                        height = Math.max(minHeight, height);
                    }

                    height = adjustVerticalRhythm($this, height);

                    // prevent blinking effects
                    $this.height(height);

                    timthumbParams = {
                        src: data.url || "",
                        a: data.gravity || "",
                        w: getNativeLength(width),
                        h: getNativeLength(height)
                    };

                    $this.attr("src", settings.timthumbPath + "?" + $.param(timthumbParams));
                });
            };

        $(window)
            .one("load", scale)
            .on(settings.windowEvents, scale);

        return this;
    };
})(jQuery, window);
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2012 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/*****************************************************************************/

var dbus = { // hook object for dbus types not translated by python-json
		Double: function(value, level) {
			return value;
		}
};

/*****************************************************************************/

var cloudeebus = window.cloudeebus = {version: "0.2.1"};

cloudeebus.reset = function() {
	cloudeebus.sessionBus = null;
	cloudeebus.systemBus = null;
	cloudeebus.wampSession = null;
	cloudeebus.uri = null;
};

cloudeebus.log = function(msg) {
};

cloudeebus.connect = function(uri, manifest, successCB, errorCB) {
	cloudeebus.reset();
	cloudeebus.uri = uri;

	function onCloudeebusVersionCheckCB(version) {
		if (cloudeebus.version == version) {
			cloudeebus.log("Connected to " + cloudeebus.uri);
			if (successCB)
				successCB();
		} else {
			var errorMsg = "Cloudeebus server version " + version + " and client version " + cloudeebus.version + " mismatch";
			cloudeebus.log(errorMsg);
			if (errorCB)
				errorCB(errorMsg);
		}
	}

	function onWAMPSessionAuthErrorCB(error) {
		cloudeebus.log("Authentication error: " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	function onWAMPSessionAuthenticatedCB(permissions) {
		cloudeebus.sessionBus = new cloudeebus.BusConnection("session", cloudeebus.wampSession);
		cloudeebus.systemBus = new cloudeebus.BusConnection("system", cloudeebus.wampSession);
		cloudeebus.wampSession.call("getVersion").then(onCloudeebusVersionCheckCB, errorCB);
	}

	function onWAMPSessionChallengedCB(challenge) {
		var signature = cloudeebus.wampSession.authsign(challenge, manifest.key);
		cloudeebus.wampSession.auth(signature).then(onWAMPSessionAuthenticatedCB, onWAMPSessionAuthErrorCB);
	}

	function onWAMPSessionConnectedCB(session) {
		cloudeebus.wampSession = session;
		if (manifest)
			cloudeebus.wampSession.authreq(
					manifest.name,
					{permissions: JSON.stringify(manifest.permissions)}
				).then(onWAMPSessionChallengedCB, onWAMPSessionAuthErrorCB);
		else
			cloudeebus.wampSession.authreq().then(function() {
				cloudeebus.wampSession.auth().then(onWAMPSessionAuthenticatedCB, onWAMPSessionAuthErrorCB);
				}, onWAMPSessionAuthErrorCB);
	}

	function onWAMPSessionErrorCB(code, reason) {
		if (code == ab.CONNECTION_UNSUPPORTED) {
			cloudeebus.log("Browser is not supported");
		}
		else {
			cloudeebus.log("Failed to open session, code = " + code + ", reason = " + reason);
		}
		if (errorCB)
			errorCB(reason);
	}

	return ab.connect(cloudeebus.uri, onWAMPSessionConnectedCB, onWAMPSessionErrorCB);
};

cloudeebus.SessionBus = function() {
	return cloudeebus.sessionBus;
};

cloudeebus.SystemBus = function() {
	return cloudeebus.systemBus;
};

/*****************************************************************************/

cloudeebus.BusConnection = function(name, session) {
	this.name = name;
	this.wampSession = session;
	return this;
};

cloudeebus.BusConnection.prototype.getObject = function(busName, objectPath, introspectCB, errorCB) {
	var proxy = new cloudeebus.ProxyObject(this.wampSession, this, busName, objectPath);
	if (introspectCB)
		proxy._introspect(introspectCB, errorCB);
	return proxy;
};

/*****************************************************************************/

cloudeebus.ProxyObject = function(session, busConnection, busName, objectPath) {
	this.wampSession = session;
	this.busConnection = busConnection;
	this.busName = busName;
	this.objectPath = objectPath;
	return this;
};

cloudeebus.ProxyObject.prototype._introspect = function(successCB, errorCB) {

	var self = this;

	function getAllPropertiesSuccessCB(props) {
		for (var prop in props)
			self[prop] = props[prop];
		getAllPropertiesNextInterfaceCB();
	}

	function getAllPropertiesNextInterfaceCB() {
		if (self.propInterfaces.length > 0)
			self.callMethod("org.freedesktop.DBus.Properties",
				"GetAll",
				[self.propInterfaces.pop()],
				getAllPropertiesSuccessCB,
				errorCB ? errorCB : getAllPropertiesNextInterfaceCB);
		else {
			self.propInterfaces = null;
			if (successCB)
				successCB(self);
		}
	}

	function introspectSuccessCB(str) {
		var parser = new DOMParser();
		var xmlDoc = parser.parseFromString(str, "text/xml");
		var interfaces = xmlDoc.getElementsByTagName("interface");
		self.propInterfaces = [];
		var supportDBusProperties = false;
		for (var i=0; i < interfaces.length; i++) {
			var ifName = interfaces[i].attributes.getNamedItem("name").value;
			if (ifName == "org.freedesktop.DBus.Properties")
				supportDBusProperties = true;
			var hasProperties = false;
			var ifChild = interfaces[i].firstChild;
			while (ifChild) {
				if (ifChild.nodeName == "method") {
					var nArgs = 0;
					var metChild = ifChild.firstChild;
					while (metChild) {
						if (metChild.nodeName == "arg" &&
							metChild.attributes.getNamedItem("direction").value == "in")
								nArgs++;
						metChild = metChild.nextSibling;
					}
					self._addMethod(ifName,
							ifChild.attributes.getNamedItem("name").value,
							nArgs);
				}
				else if (ifChild.nodeName == "property") {
					if (!hasProperties)
						self.propInterfaces.push(ifName);
					hasProperties = true;
				}
				ifChild = ifChild.nextSibling;
			}
		}
		if (supportDBusProperties && self.propInterfaces.length > 0) {
			self.callMethod("org.freedesktop.DBus.Properties",
				"GetAll",
				[self.propInterfaces.pop()],
				getAllPropertiesSuccessCB,
				errorCB ? errorCB : getAllPropertiesNextInterfaceCB);
		}
		else {
			self.propInterfaces = null;
			if (successCB)
				successCB(self);
		}
	}

	// call Introspect on self
	self.callMethod("org.freedesktop.DBus.Introspectable", "Introspect", [], introspectSuccessCB, errorCB);
};

cloudeebus.ProxyObject.prototype._addMethod = function(ifName, method, nArgs) {

	var self = this;

	self[method] = function() {
		if (arguments.length < nArgs || arguments.length > nArgs + 2)
			throw "Error: method " + method + " takes " + nArgs + " parameters, got " + arguments.length + ".";
		var args = [];
		var successCB = null;
		var errorCB = null;
		for (var i=0; i < nArgs; i++ )
			args.push(arguments[i]);
		if (arguments.length > nArgs)
			successCB = arguments[nArgs];
		if (arguments.length > nArgs + 1)
			errorCB = arguments[nArgs + 1];
		self.callMethod(ifName, method, args, successCB, errorCB);
	};

};

cloudeebus.ProxyObject.prototype.callMethod = function(ifName, method, args, successCB, errorCB) {

	var self = this;

	function callMethodSuccessCB(str) {
		if (successCB) {
			try { // calling dbus hook object function for un-translated types
				successCB.apply(self, eval(str));
			}
			catch (e) {
				cloudeebus.log("Method callback exception: " + e);
				if (errorCB)
					errorCB(e);
			}
		}
	}

	function callMethodErrorCB(error) {
		cloudeebus.log("Error calling method: " + method + " on object: " + self.objectPath + " : " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	var arglist = [
		self.busConnection.name,
		self.busName,
		self.objectPath,
		ifName,
		method,
		JSON.stringify(args)
	];

	// call dbusSend with bus type, destination, object, message and arguments
	self.wampSession.call("dbusSend", arglist).then(callMethodSuccessCB, callMethodErrorCB);
};

cloudeebus.ProxyObject.prototype.connectToSignal = function(ifName, signal, successCB, errorCB) {

	var self = this;

	function signalHandler(id, data) {
		if (successCB) {
			try { // calling dbus hook object function for un-translated types
				successCB.apply(self, eval(data));
			}
			catch (e) {
				cloudeebus.log("Signal handler exception: " + e);
				if (errorCB)
					errorCB(e);
			}
		}
	}

	function connectToSignalSuccessCB(str) {
		try {
			self.wampSession.subscribe(str, signalHandler);
		}
		catch (e) {
			cloudeebus.log("Subscribe error: " + e);
		}
	}

	function connectToSignalErrorCB(error) {
		cloudeebus.log("Error connecting to signal: " + signal + " on object: " + self.objectPath + " : " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	var arglist = [
		self.busConnection.name,
		self.busName,
		self.objectPath,
		ifName,
		signal
	];

	// call dbusSend with bus type, destination, object, message and arguments
	self.wampSession.call("dbusRegister", arglist).then(connectToSignalSuccessCB, connectToSignalErrorCB);
};

cloudeebus.ProxyObject.prototype.disconnectSignal = function(ifName, signal) {
	try {
		this.wampSession.unsubscribe(this.busConnection.name + "#" + this.busName + "#" + this.objectPath + "#" + ifName + "#" + signal);
	}
	catch (e) {
		cloudeebus.log("Unsubscribe error: " + e);
	}
};
<commit_msg>cloudeebus js library v0.3.0<commit_after>/******************************************************************************
 * Copyright 2012 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/*****************************************************************************/

var dbus = { // hook object for dbus types not translated by python-json
		Double: function(value, level) {
			return value;
		}
};

/*****************************************************************************/

var cloudeebus = window.cloudeebus = {version: "0.3.0"};

cloudeebus.reset = function() {
	cloudeebus.sessionBus = null;
	cloudeebus.systemBus = null;
	cloudeebus.wampSession = null;
	cloudeebus.uri = null;
};

cloudeebus.log = function(msg) {
};

cloudeebus.connect = function(uri, manifest, successCB, errorCB) {
	cloudeebus.reset();
	cloudeebus.uri = uri;

	function onCloudeebusVersionCheckCB(version) {
		if (cloudeebus.version == version) {
			cloudeebus.log("Connected to " + cloudeebus.uri);
			if (successCB)
				successCB();
		} else {
			var errorMsg = "Cloudeebus server version " + version + " and client version " + cloudeebus.version + " mismatch";
			cloudeebus.log(errorMsg);
			if (errorCB)
				errorCB(errorMsg);
		}
	}

	function onWAMPSessionAuthErrorCB(error) {
		cloudeebus.log("Authentication error: " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	function onWAMPSessionAuthenticatedCB(permissions) {
		cloudeebus.sessionBus = new cloudeebus.BusConnection("session", cloudeebus.wampSession);
		cloudeebus.systemBus = new cloudeebus.BusConnection("system", cloudeebus.wampSession);
		cloudeebus.wampSession.call("getVersion").then(onCloudeebusVersionCheckCB, errorCB);
	}

	function onWAMPSessionChallengedCB(challenge) {
		var signature = cloudeebus.wampSession.authsign(challenge, manifest.key);
		cloudeebus.wampSession.auth(signature).then(onWAMPSessionAuthenticatedCB, onWAMPSessionAuthErrorCB);
	}

	function onWAMPSessionConnectedCB(session) {
		cloudeebus.wampSession = session;
		if (manifest)
			cloudeebus.wampSession.authreq(
					manifest.name,
					{permissions: JSON.stringify(manifest.permissions)}
				).then(onWAMPSessionChallengedCB, onWAMPSessionAuthErrorCB);
		else
			cloudeebus.wampSession.authreq().then(function() {
				cloudeebus.wampSession.auth().then(onWAMPSessionAuthenticatedCB, onWAMPSessionAuthErrorCB);
				}, onWAMPSessionAuthErrorCB);
	}

	function onWAMPSessionErrorCB(code, reason) {
		if (code == ab.CONNECTION_UNSUPPORTED) {
			cloudeebus.log("Browser is not supported");
		}
		else {
			cloudeebus.log("Failed to open session, code = " + code + ", reason = " + reason);
		}
		if (errorCB)
			errorCB(reason);
	}

	return ab.connect(cloudeebus.uri, onWAMPSessionConnectedCB, onWAMPSessionErrorCB);
};

cloudeebus.SessionBus = function() {
	return cloudeebus.sessionBus;
};

cloudeebus.SystemBus = function() {
	return cloudeebus.systemBus;
};

/*****************************************************************************/

cloudeebus.BusConnection = function(name, session) {
	this.name = name;
	this.wampSession = session;
	return this;
};

cloudeebus.BusConnection.prototype.getObject = function(busName, objectPath, introspectCB, errorCB) {
	var proxy = new cloudeebus.ProxyObject(this.wampSession, this, busName, objectPath);
	if (introspectCB)
		proxy._introspect(introspectCB, errorCB);
	return proxy;
};

/*****************************************************************************/

cloudeebus.ProxyObject = function(session, busConnection, busName, objectPath) {
	this.wampSession = session;
	this.busConnection = busConnection;
	this.busName = busName;
	this.objectPath = objectPath;
	this.interfaceProxies = {};
	return this;
};

cloudeebus.ProxyObject.prototype.getInterface = function(ifName) {
	return this.interfaceProxies[ifName];
};

cloudeebus.ProxyObject.prototype._introspect = function(successCB, errorCB) {

	var self = this;

	function getAllPropertiesSuccessCB(props) {
		var ifProxy = self.interfaceProxies[self.propInterfaces[self.propInterfaces.length-1]];
		for (var prop in props)
			ifProxy[prop] = self[prop] = props[prop];
		getAllPropertiesNextInterfaceCB();
	}

	function getAllPropertiesNextInterfaceCB() {
		self.propInterfaces.pop();
		if (self.propInterfaces.length > 0)
			self.callMethod("org.freedesktop.DBus.Properties",
				"GetAll",
				[self.propInterfaces[self.propInterfaces.length-1]],
				getAllPropertiesSuccessCB,
				errorCB ? errorCB : getAllPropertiesNextInterfaceCB);
		else {
			self.propInterfaces = null;
			if (successCB)
				successCB(self);
		}
	}

	function introspectSuccessCB(str) {
		var parser = new DOMParser();
		var xmlDoc = parser.parseFromString(str, "text/xml");
		var interfaces = xmlDoc.getElementsByTagName("interface");
		self.propInterfaces = [];
		var supportDBusProperties = false;
		for (var i=0; i < interfaces.length; i++) {
			var ifName = interfaces[i].attributes.getNamedItem("name").value;
			self.interfaceProxies[ifName] = new cloudeebus.ProxyObject(self.wampSession, self.busConnection, self.busName, self.objectPath);
			if (ifName == "org.freedesktop.DBus.Properties")
				supportDBusProperties = true;
			var hasProperties = false;
			var ifChild = interfaces[i].firstChild;
			while (ifChild) {
				if (ifChild.nodeName == "method") {
					var nArgs = 0;
					var metChild = ifChild.firstChild;
					while (metChild) {
						if (metChild.nodeName == "arg" &&
							metChild.attributes.getNamedItem("direction").value == "in")
								nArgs++;
						metChild = metChild.nextSibling;
					}
					var metName = ifChild.attributes.getNamedItem("name").value;
					if (!self[metName])
						self._addMethod(ifName, metName, nArgs);
					self.interfaceProxies[ifName]._addMethod(ifName, metName, nArgs);
				}
				else if (ifChild.nodeName == "property") {
					if (!hasProperties)
						self.propInterfaces.push(ifName);
					hasProperties = true;
				}
				ifChild = ifChild.nextSibling;
			}
		}
		if (supportDBusProperties && self.propInterfaces.length > 0) {
			self.callMethod("org.freedesktop.DBus.Properties",
				"GetAll",
				[self.propInterfaces[self.propInterfaces.length-1]],
				getAllPropertiesSuccessCB,
				errorCB ? errorCB : getAllPropertiesNextInterfaceCB);
		}
		else {
			self.propInterfaces = null;
			if (successCB)
				successCB(self);
		}
	}

	// call Introspect on self
	self.callMethod("org.freedesktop.DBus.Introspectable", "Introspect", [], introspectSuccessCB, errorCB);
};

cloudeebus.ProxyObject.prototype._addMethod = function(ifName, method, nArgs) {

	var self = this;

	self[method] = function() {
		if (arguments.length < nArgs || arguments.length > nArgs + 2)
			throw "Error: method " + method + " takes " + nArgs + " parameters, got " + arguments.length + ".";
		var args = [];
		var successCB = null;
		var errorCB = null;
		for (var i=0; i < nArgs; i++ )
			args.push(arguments[i]);
		if (arguments.length > nArgs)
			successCB = arguments[nArgs];
		if (arguments.length > nArgs + 1)
			errorCB = arguments[nArgs + 1];
		self.callMethod(ifName, method, args, successCB, errorCB);
	};

};

cloudeebus.ProxyObject.prototype.callMethod = function(ifName, method, args, successCB, errorCB) {

	var self = this;

	function callMethodSuccessCB(str) {
		if (successCB) {
			try { // calling dbus hook object function for un-translated types
				successCB.apply(self, eval(str));
			}
			catch (e) {
				cloudeebus.log("Method callback exception: " + e);
				if (errorCB)
					errorCB(e);
			}
		}
	}

	function callMethodErrorCB(error) {
		cloudeebus.log("Error calling method: " + method + " on object: " + self.objectPath + " : " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	var arglist = [
		self.busConnection.name,
		self.busName,
		self.objectPath,
		ifName,
		method,
		JSON.stringify(args)
	];

	// call dbusSend with bus type, destination, object, message and arguments
	self.wampSession.call("dbusSend", arglist).then(callMethodSuccessCB, callMethodErrorCB);
};

cloudeebus.ProxyObject.prototype.connectToSignal = function(ifName, signal, successCB, errorCB) {

	var self = this;

	function signalHandler(id, data) {
		if (successCB) {
			try { // calling dbus hook object function for un-translated types
				successCB.apply(self, eval(data));
			}
			catch (e) {
				cloudeebus.log("Signal handler exception: " + e);
				if (errorCB)
					errorCB(e);
			}
		}
	}

	function connectToSignalSuccessCB(str) {
		try {
			self.wampSession.subscribe(str, signalHandler);
		}
		catch (e) {
			cloudeebus.log("Subscribe error: " + e);
		}
	}

	function connectToSignalErrorCB(error) {
		cloudeebus.log("Error connecting to signal: " + signal + " on object: " + self.objectPath + " : " + error.desc);
		if (errorCB)
			errorCB(error.desc);
	}

	var arglist = [
		self.busConnection.name,
		self.busName,
		self.objectPath,
		ifName,
		signal
	];

	// call dbusSend with bus type, destination, object, message and arguments
	self.wampSession.call("dbusRegister", arglist).then(connectToSignalSuccessCB, connectToSignalErrorCB);
};

cloudeebus.ProxyObject.prototype.disconnectSignal = function(ifName, signal) {
	try {
		this.wampSession.unsubscribe(this.busConnection.name + "#" + this.busName + "#" + this.objectPath + "#" + ifName + "#" + signal);
	}
	catch (e) {
		cloudeebus.log("Unsubscribe error: " + e);
	}
};
<|endoftext|>