<commit_before>var assert = require('assert');
var Bridge = require('..');
var path = require('path');
var fs = require('fs');

// Load fixture data.
var xml = {
    a: fs.readFileSync(path.resolve(__dirname + '/test-a.xml'), 'utf8'),
    b: fs.readFileSync(path.resolve(__dirname + '/test-b.xml'), 'utf8')
};

describe('init', function() {
    it('should fail without xml', function(done) {
        new Bridge({}, function(err) {
            assert.equal(err.message, 'No xml');
            done();
        });
    });
    it('should load with callback', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            done();
        });
    });
    it('should load from filepath', function(done) {
        new Bridge('bridge://' + path.resolve(__dirname + '/test-a.xml'), function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            assert.equal(source._blank, true);
            assert.equal(source._deflate, true);
            assert.equal(source._xml, xml.a);
            assert.equal(source._base, __dirname);
            done();
        });
    });
    it('should load query params', function(done) {
        new Bridge('bridge://' + path.resolve(__dirname + '/test-a.xml?blank=0&deflate=0'), function(err, source) {
            assert.ifError(err);
            assert.equal(source._blank, false);
            assert.equal(source._deflate, false);
            assert.equal(source._xml, xml.a);
            assert.equal(source._base, __dirname);
            done();
        });
    });
    it('#open should call all listeners', function(done) {
        var b = new Bridge({ xml: xml.a, base:__dirname + '/' });
        var remaining = 3;
        for (var i = 0, l = remaining; i < l; i++) b.open(function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            if (!--remaining) done();
        });
    });
    it('should get info', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            source.getInfo(function(err, info) {
                assert.ifError(err);
                assert.equal('test-a', info.name);
                assert.equal(0, info.minzoom);
                assert.equal(8, info.maxzoom);
                assert.deepEqual([0,0,2], info.center);
                assert.deepEqual([-180,-85.0511,180,85.0511], info.bounds);
                assert.deepEqual({"level2":"property"}, info.level1, 'JSON key stores deep attribute data');
                assert.deepEqual(0, info.minzoom, 'JSON key does not overwrite other params');
                done();
            });
        });
    });
    it('should update xml', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            source.getInfo(function(err, info) {
                assert.ifError(err);
                assert.equal('test-a', info.name);
                source.update({xml:xml.b}, function(err) {
                    assert.ifError(err);
                    source.getInfo(function(err, info) {
                        assert.ifError(err);
                        assert.equal('test-b', info.name);
                        done();
                    });
                });
            });
        });
    });
});

describe('tiles', function() {
    var sources = {
        a: new Bridge({ xml:xml.a, base:__dirname + '/' }),
        b: new Bridge({ xml:xml.b, base:__dirname + '/', deflate:false }),
        c: new Bridge({ xml:xml.a, base:__dirname + '/', blank:false })
    };
    var tests = {
        a: ['0.0.0', '1.0.0', '1.0.1', {key:'10.0.0',solid:'0,0,0,0'}, {key:'10.765.295',solid:'0,0,0,0'}],
        b: ['0.0.0'],
        c: [{key:'10.0.0',solid:'0,0,0,0'}, {key:'10.765.295', solid:'125,121,48,1'}]
    };
    Object.keys(tests).forEach(function(source) {
        before(function(done) { sources[source].open(done); });
    });
    Object.keys(tests).forEach(function(source) {
        tests[source].forEach(function(obj) {
            var key = obj.key ? obj.key : obj;
            var z = key.split('.')[0] | 0;
            var x = key.split('.')[1] | 0;
            var y = key.split('.')[2] | 0;
            it('should render ' + source + ' (' + key + ')', function(done) {
                sources[source].getTile(z,x,y, function(err, buffer, headers) {
                    assert.ifError(err);
                    assert.equal(headers['Content-Type'], 'application/x-protobuf');
                    assert.equal(headers['Content-Encoding'], source !== 'b' ? 'deflate' : undefined);

                    // Test solid key generation.
                    if (obj.solid) assert.equal(buffer.solid, obj.solid);

                    var filepath = __dirname + '/expected/' + source + '.' + key + '.vector.pbf';
                    //fs.writeFileSync(filepath, buffer);
                    var expected = fs.readFileSync(filepath);
                    assert.equal(expected.length, buffer.length);
                    assert.deepEqual(expected, buffer);
                    done();
                });
            });
        });
    });
});

<commit_msg>more rich test comparisons to help figure out failures<commit_after>var assert = require('assert');
var Bridge = require('..');
var path = require('path');
var fs = require('fs');
var mapnik = require('mapnik');
var zlib = require('zlib');

// Load fixture data.
var xml = {
    a: fs.readFileSync(path.resolve(__dirname + '/test-a.xml'), 'utf8'),
    b: fs.readFileSync(path.resolve(__dirname + '/test-b.xml'), 'utf8')
};

describe('init', function() {
    it('should fail without xml', function(done) {
        new Bridge({}, function(err) {
            assert.equal(err.message, 'No xml');
            done();
        });
    });
    it('should load with callback', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            done();
        });
    });
    it('should load from filepath', function(done) {
        new Bridge('bridge://' + path.resolve(__dirname + '/test-a.xml'), function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            assert.equal(source._blank, true);
            assert.equal(source._deflate, true);
            assert.equal(source._xml, xml.a);
            assert.equal(source._base, __dirname);
            done();
        });
    });
    it('should load query params', function(done) {
        new Bridge('bridge://' + path.resolve(__dirname + '/test-a.xml?blank=0&deflate=0'), function(err, source) {
            assert.ifError(err);
            assert.equal(source._blank, false);
            assert.equal(source._deflate, false);
            assert.equal(source._xml, xml.a);
            assert.equal(source._base, __dirname);
            done();
        });
    });
    it('#open should call all listeners', function(done) {
        var b = new Bridge({ xml: xml.a, base:__dirname + '/' });
        var remaining = 3;
        for (var i = 0, l = remaining; i < l; i++) b.open(function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            if (!--remaining) done();
        });
    });
    it('should get info', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            source.getInfo(function(err, info) {
                assert.ifError(err);
                assert.equal('test-a', info.name);
                assert.equal(0, info.minzoom);
                assert.equal(8, info.maxzoom);
                assert.deepEqual([0,0,2], info.center);
                assert.deepEqual([-180,-85.0511,180,85.0511], info.bounds);
                assert.deepEqual({"level2":"property"}, info.level1, 'JSON key stores deep attribute data');
                assert.deepEqual(0, info.minzoom, 'JSON key does not overwrite other params');
                done();
            });
        });
    });
    it('should update xml', function(done) {
        new Bridge({ xml: xml.a, base:__dirname + '/' }, function(err, source) {
            assert.ifError(err);
            assert.ok(source);
            source.getInfo(function(err, info) {
                assert.ifError(err);
                assert.equal('test-a', info.name);
                source.update({xml:xml.b}, function(err) {
                    assert.ifError(err);
                    source.getInfo(function(err, info) {
                        assert.ifError(err);
                        assert.equal('test-b', info.name);
                        done();
                    });
                });
            });
        });
    });
});

function show_json(filepath,vtile1,vtile2) {
    var e = filepath+'.expected.json';
    var a = filepath+'.actual.json';
    fs.writeFileSync(e,JSON.stringify(vtile1,null,2));
    fs.writeFileSync(a,JSON.stringify(vtile2,null,2));
    throw new Error('files json representations differs: \n'+e + '\n' + a + '\n');
}

function compare_vtiles(vtile1,vtile2) {
    assert.equal(vtile1.width(),vtile2.width());
    assert.equal(vtile1.height(),vtile2.height());
    assert.deepEqual(vtile1.names(),vtile2.names());
    v1 = vtile1.toJSON();
    v2 = vtile2.toJSON();
    assert.deepEqual(vtile1.names(),vtile2.names());
    try {
      assert.deepEqual(v1,v2);
    } catch (err) {
      show_json(filepath,v1,v2);
    }
}

describe('tiles', function() {
    var sources = {
        a: new Bridge({ xml:xml.a, base:__dirname + '/' }),
        b: new Bridge({ xml:xml.b, base:__dirname + '/', deflate:false }),
        c: new Bridge({ xml:xml.a, base:__dirname + '/', blank:false })
    };
    var tests = {
        a: ['0.0.0', '1.0.0', '1.0.1', {key:'10.0.0',solid:'0,0,0,0'}, {key:'10.765.295',solid:'0,0,0,0'}],
        b: ['0.0.0'],
        c: [{key:'10.0.0',solid:'0,0,0,0'}, {key:'10.765.295', solid:'125,121,48,1'}]
    };
    Object.keys(tests).forEach(function(source) {
        before(function(done) { sources[source].open(done); });
    });
    Object.keys(tests).forEach(function(source) {
        tests[source].forEach(function(obj) {
            var key = obj.key ? obj.key : obj;
            var z = key.split('.')[0] | 0;
            var x = key.split('.')[1] | 0;
            var y = key.split('.')[2] | 0;
            it('should render ' + source + ' (' + key + ')', function(done) {
                sources[source].getTile(z,x,y, function(err, buffer, headers) {
                    assert.ifError(err);
                    assert.equal(headers['Content-Type'], 'application/x-protobuf');
                    assert.equal(headers['Content-Encoding'], source !== 'b' ? 'deflate' : undefined);

                    // Test solid key generation.
                    if (obj.solid) assert.equal(buffer.solid, obj.solid);

                    var filepath = __dirname + '/expected/' + source + '.' + key + '.vector.pbf';
                    //fs.writeFileSync(filepath, buffer);
                    var expected = fs.readFileSync(filepath);
                    var vtile1 = new mapnik.VectorTile(+z,+x,+y);
                    var vtile2 = new mapnik.VectorTile(+z,+x,+y);
                    if (headers['Content-Encoding'] == 'deflate') {
                        zlib.inflate(expected,function(err,expected_inflated) {
                            vtile1.setData(expected_inflated);
                            zlib.inflate(buffer,function(err,buffer_inflated) {
                                vtile2.setData(buffer_inflated);
                                compare_vtiles(vtile1,vtile2);
                            });
                        });
                    } else {
                        vtile1.setData(expected);
                        vtile2.setData(buffer);
                        compare_vtiles(vtile1,vtile2);
                    }
                    assert.equal(expected.length, buffer.length);
                    assert.deepEqual(expected, buffer);
                    done();
                });
            });
        });
    });
});

<|endoftext|>


<commit_before>/*
Copyright 2017 Vector Creations Ltd

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.
*/

import React from 'react';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import MatrixClientPeg from '../../../MatrixClientPeg';
import DMRoomMap from '../../../utils/DMRoomMap';
import AccessibleButton from '../elements/AccessibleButton';
import Unread from '../../../Unread';
import classNames from 'classnames';
import createRoom from '../../../createRoom';

export default class CreateOrReuseChatDialog extends React.Component {

    constructor(props) {
        super(props);
        this._onNewDMClick = this._onNewDMClick.bind(this);
        dis.register(this._onAction.bind(this));
    }

    _onAction(payload) {
        switch(payload.action) {
            case 'view_room':
                this.props.onFinished(true);
                break;
            default:
        }
    }

    _onNewDMClick() {
        createRoom({dmUserId: this.props.userId});
        this.props.onFinished(true);
    }

    render() {
        const client = MatrixClientPeg.get();

        const dmRoomMap = new DMRoomMap(client);
        const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.userId);

        const RoomTile = sdk.getComponent("rooms.RoomTile");

        const tiles = [];
        for (const roomId of dmRooms) {
            const room = client.getRoom(roomId);
            if (room) {
                const me = room.getMember(client.credentials.userId);
                const highlight = (
                    room.getUnreadNotificationCount('highlight') > 0 ||
                    me.membership == "invite"
                );
                tiles.push(
                    <RoomTile key={room.roomId} room={room}
                        collapsed={false}
                        selected={false}
                        unread={Unread.doesRoomHaveUnreadMessages(room)}
                        highlight={highlight}
                        isInvite={me.membership == "invite"}
                    />
                );
            }
        }

        const labelClasses = classNames({
            mx_MemberInfo_createRoom_label: true,
            mx_RoomTile_name: true,
        });
        const startNewChat = <AccessibleButton
            className="mx_MemberInfo_createRoom"
            onClick={this._onNewDMClick}
        >

Start new chat

        </AccessibleButton>;

        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
        return (
            <BaseDialog className='mx_CreateOrReuseChatDialog'
                onFinished={() => {
                    this.props.onFinished(false)
                }}
                title='Create a new chat or reuse an existing one'
            >
                You already have existing direct chats with this user:
                {tiles}
                {startNewChat}
            </BaseDialog>
        );
    }
}

CreateOrReuseChatDialog.propTyps = {
    userId: React.PropTypes.string.isRequired,
    onFinished: React.PropTypes.func.isRequired,
};
<commit_msg>Remember to unregister on unmoun<commit_after>/*
Copyright 2017 Vector Creations Ltd

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.
*/

import React from 'react';
import sdk from '../../../index';
import dis from '../../../dispatcher';
import MatrixClientPeg from '../../../MatrixClientPeg';
import DMRoomMap from '../../../utils/DMRoomMap';
import AccessibleButton from '../elements/AccessibleButton';
import Unread from '../../../Unread';
import classNames from 'classnames';
import createRoom from '../../../createRoom';

export default class CreateOrReuseChatDialog extends React.Component {

    constructor(props) {
        super(props);
        this._onNewDMClick = this._onNewDMClick.bind(this);
        this.dispatcherRef = dis.register(this._onAction.bind(this));
    }

    componentWillUnmount() {
        dis.unregister(this.dispatcherRef);
    }

    _onAction(payload) {
        switch(payload.action) {
            case 'view_room':
                this.props.onFinished(true);
                break;
            default:
        }
    }

    _onNewDMClick() {
        createRoom({dmUserId: this.props.userId});
        this.props.onFinished(true);
    }

    render() {
        const client = MatrixClientPeg.get();

        const dmRoomMap = new DMRoomMap(client);
        const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.userId);

        const RoomTile = sdk.getComponent("rooms.RoomTile");

        const tiles = [];
        for (const roomId of dmRooms) {
            const room = client.getRoom(roomId);
            if (room) {
                const me = room.getMember(client.credentials.userId);
                const highlight = (
                    room.getUnreadNotificationCount('highlight') > 0 ||
                    me.membership == "invite"
                );
                tiles.push(
                    <RoomTile key={room.roomId} room={room}
                        collapsed={false}
                        selected={false}
                        unread={Unread.doesRoomHaveUnreadMessages(room)}
                        highlight={highlight}
                        isInvite={me.membership == "invite"}
                    />
                );
            }
        }

        const labelClasses = classNames({
            mx_MemberInfo_createRoom_label: true,
            mx_RoomTile_name: true,
        });
        const startNewChat = <AccessibleButton
            className="mx_MemberInfo_createRoom"
            onClick={this._onNewDMClick}
        >

Start new chat

        </AccessibleButton>;

        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
        return (
            <BaseDialog className='mx_CreateOrReuseChatDialog'
                onFinished={() => {
                    this.props.onFinished(false)
                }}
                title='Create a new chat or reuse an existing one'
            >
                You already have existing direct chats with this user:
                {tiles}
                {startNewChat}
            </BaseDialog>
        );
    }
}

CreateOrReuseChatDialog.propTyps = {
    userId: React.PropTypes.string.isRequired,
    onFinished: React.PropTypes.func.isRequired,
};
<|endoftext|>


<commit_before>/**
* for creating different type of questionnaire ui;
*@author Awais
*
*/

var DZHK = DZHK || {};

/**
*Generic Super Answer Class to inherit from
*more like an abstract class
*
*@constructor
*@param Fhir question object
*
*/
DZHK.Answer=function(question){
	this.question=question;
};

DZHK.Answer.prototype.question={};

/**
* To generate html for the response.
* @return string html for response interaction
*/
DZHK.Answer.prototype.generateUI=function(){
	return "
:)
";
};

/**
*use it to save different type of answers
*/
DZHK.Answer.prototype.saveAnswer=function(){
	alert("Implement a sub class");
};

/**
*to render the ui, adding listeners and saving response collected
*
*/
DZHK.Answer.prototype.render=function(selector){
	$(selector).html("default Render:"+this.generateUI());
};

DZHK.Answer.prototype.parseExtension=function(){
	var self=this;
	var ext={
		type:null,
		code:"",
		orientation:"vertical" //default Orientation;
	};

	try{
		if(this.question.extension && this.question.extension.length>0){
			for (var i = this.question.extension.length - 1; i >= 0; i--) {
				//this.question.extension[i]
				var type=this.checkExtensionFromUrl(this.question.extension[i]);
				if(type=="questionnaire-questionControl"){
					ext.type=type;
					ext.code=this.question.extension[i].valueCodeableConcept.coding[0].code;
				}else if(type=="questionnaire-choiceOrientation"){
					ext.orientation=this.question.extension[i].valueCode;
				}
			}
		}else{
			console.log("no extension found");
		}
	}catch(ex){
		console.error("problem parsing extension for question linkId"+self.question.linkId);
	}
	return ext;

};
DZHK.Answer.prototype.checkExtensionFromUrl=function(extension){

	if(typeof extension.url == "string"){
		return extension.url.substr(extension.url.lastIndexOf("/")+1,extension.url.length);
	}else{
		//undefined!
		return "undefined"
	}

};

DZHK.Answer.prototype.checkValueCodeableConcept=function(extension){
	if(typeof extension.valueCodeableConcept == "object"){
		return true;
	}else{
		return false;
	}
};

/**
* Sub classes for each specific type
* TextAnswer will generate TextArea
*/

DZHK.TextAnswer=function(){};
DZHK.TextAnswer=function(question){
	this.question=question;
};
DZHK.TextAnswer.prototype=new DZHK.Answer;
DZHK.TextAnswer.prototype.constructor=new DZHK.Answer;
DZHK.TextAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<textarea class='form-control' rows='3' placeholder='Enter ...'></textarea>"+
                "
"+
            "
";
    return html;
};
DZHK.TextAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" textarea");
	$(input).change(function(){
		self.question.answer={
			"valueText":$(this).val()
		}
	});
};

DZHK.DateAnswer=function(question){
	this.question=question;
};
DZHK.DateAnswer.prototype=new DZHK.Answer;
DZHK.DateAnswer.prototype.constructor=new DZHK.Answer;
DZHK.DateAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control' />"+
                    ""+
                        ""+
                    ""+
                "
"+
            "
";
    return html;
};
DZHK.DateAnswer.prototype.render=function(selector){
	var that=this;
	$(selector).html(this.generateUI());
	//initiate datetimepicker
	var answerDatePicker=$(selector+" #answer-"+this.question.linkId).datetimepicker({
		locale: 'de',
		format: 'L'
	});

	//save answer
	$(answerDatePicker).on("dp.change",function(e){
		that.question.answer={
			"valueDate":e.date.format("L")
		}
	});
};

DZHK.DateTimeAnswer=function(question){
	this.question=question;
};
DZHK.DateTimeAnswer.prototype=new DZHK.Answer;
DZHK.DateTimeAnswer.prototype.constructor=new DZHK.Answer;
DZHK.DateTimeAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control' />"+
                    ""+
                        ""+
                    ""+
                "
"+
            "
";
    return html;
};
DZHK.DateTimeAnswer.prototype.render=function(selector){
	var that=this;
	$(selector).html(this.generateUI());
	//initiate datetimepicker
	var answerDatePicker=$(selector+" #answer-"+this.question.linkId).datetimepicker({
		sideBySide:true,
		locale: 'de'
	});

	//save answer
	$(answerDatePicker).on("dp.change",function(e){
		that.question.answer={
			"valueDateTime":e.date.format() //(ISO 8601)
		}
	});
};

/**
*	IntegerAnswer Class
*/
DZHK.IntegerAnswer=function(question){
	this.question=question;
};
DZHK.IntegerAnswer.prototype=new DZHK.Answer;
DZHK.IntegerAnswer.prototype.constructor=new DZHK.Answer;
DZHK.IntegerAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control'/>"+
                "
"+
            "
";
    return html;
};
DZHK.IntegerAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" input");
	$(input).change(function(){
		self.question.answer={
			"valueInteger":$(this).val()
		}
	});
};

/**
*	StringAnswer Class inherited from integer
*/
DZHK.StringAnswer=function(question){
	this.question=question;
};
DZHK.StringAnswer.prototype=new DZHK.IntegerAnswer;
DZHK.StringAnswer.prototype.constructor=new DZHK.IntegerAnswer;
//can use integerClass generate ui function, validation may differ TODO: add validations later, if required
DZHK.IntegerAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" input");
	$(input).change(function(){
		self.question.answer={
			"valueString":$(this).val()
		}
	});
};

/**
*	ChoiceAnswer Class inherited from integer
*/
DZHK.ChoiceAnswer=function(question){
	this.question=question;
};
DZHK.ChoiceAnswer.prototype=new DZHK.Answer;
DZHK.ChoiceAnswer.prototype.constructor=new DZHK.Answer;

DZHK.ChoiceAnswer.prototype.generateUI=function(ext){

	var html="";
	if(ext.type=="questionnaire-questionControl"){
		if(ext.code=="radio-button"){
				html= "
";
					for (var i = 0; i < this.question.option.length; i++) {
						html+="";
						}else{
							html+=" >"
							br="
"
						}
						html+="<input type='radio' name='iCheck' value='"+this.question.option[i].code+"'/> "+
						this.question.option[i].display+
						""+br;
					}
				html+="
";
		}else if(ext.code=="check-box"){
			//more or less same.
			html= "
";
					for (var i = 0; i < this.question.option.length; i++) {
						html+="";
						}else{
							html+=" >"
							br="
"
						}
						html+="<input type='checkbox' name='iCheck' value='"+this.question.option[i].code+"'/> "+
						this.question.option[i].display+
						""+br;
					}
				html+="
";

		}else{
			html="unsupported! questioncontrol extension type";
		}
	}
	return html;
}

DZHK.ChoiceAnswer.prototype.render=function(selector){
	// have to check options
	var self= this;

	this.question.answer=[];

	//check extensions
	var ext=this.parseExtension();
	if(this.question.group){
		if(this.question.options){
			this.containsOptionsReference();
		}
		this.containsGroup();
	}else{
		if(ext.type){
			$(selector).html(this.generateUI(ext));

			if(ext.type=="questionnaire-questionControl" && ext.code=="radio-button"){
				$(selector+" #answer-"+this.question.linkId+" input[type='radio']").iCheck({
					radioClass: 'iradio_flat-blue'
				}).on("ifClicked",function(event){
					//answer=this.value;
					//store the answer;
					var ans=this.value;
					self.question.answer={
						"code":ans,
						"display":$(this).parent().parent().text().trim()
					};
				});
			}else if(ext.type=="questionnaire-questionControl" && ext.code=="check-box"){
				$(selector+" #answer-"+this.question.linkId+" input[type='checkbox']").iCheck({
					checkboxClass: 'icheckbox_flat-blue'
				}).on("ifChecked",function(event){
					//answer=this.value;

					var ans=this.value;
					 var answer={
					 	code:ans,
					 	display:$(this).parent().parent().text().trim()
					 };
					self.question.answer.push(answer);
				}).on("ifUnchecked",function(event){
					 var answer={
					 	code:this.value,
					 	display:$(this).parent().parent().text().trim()
					 };
					self.removeCheckBoxAnswer(answer);
				});
			}
		}else{
			//console.error("unsupported type!");
		}
	}

};

DZHK.ChoiceAnswer.prototype.containsGroup=function(){
	console.error("not implemented yet: contains-Group");
};

DZHK.ChoiceAnswer.prototype.removeCheckBoxAnswer=function(answer){
	//improved
	for (var i = this.question.answer.length - 1; i >= 0; i--) {
		if (this.question.answer[i].code == answer.code) {
           this.question.answer.splice(i,1);
        }
	}
};

DZHK.ChoiceAnswer.prototype.containsOptionsReference=function(){
	console.error("not implemented yet: contains reference to valueset");
};

/**
*	OpenChoiceAnswer Class inherited from integer
*/
DZHK.OpenChoiceAnswer=function(question){
	this.question=question;
};
DZHK.OpenChoiceAnswer.prototype=new DZHK.Answer;
DZHK.OpenChoiceAnswer.prototype.constructor=new DZHK.Answer;
DZHK.OpenChoiceAnswer.prototype.render=function(selector){
	DZHK.Answer.prototype.render.call(this,selector);
	console.error("implementation incomplete");
};

/**
* factory to generate answer type objects
*factory pattern;
*/
DZHK.AnswerFactory=function(){};
DZHK.AnswerFactory.prototype.answerClass=DZHK.StringAnswer;
DZHK.AnswerFactory.prototype.createAnswerClass=function(question){
	switch(question.type){
		case "date":
			this.answerClass=DZHK.DateAnswer;
			break;
		case "dateTime":
			this.answerClass=DZHK.DateTimeAnswer;
			break;
		case "integer":
			this.answerClass=DZHK.IntegerAnswer;
			break;
		case "text":
			this.answerClass=DZHK.TextAnswer;
			break;
		case "string":
			this.answerClass=DZHK.StringAnswer;
			break;
		case "choice":
			this.answerClass=DZHK.ChoiceAnswer;
			break;
		case "open-choice":
			this.answerClass=DZHK.OpenChoiceAnswer;
			break;
		default:
			console.error("unsupported answer type:"+question.type);
	}
	return new this.answerClass(question);
};
<commit_msg>openChoice handled for radio button ony!<commit_after>/**
* for creating different type of questionnaire ui;
*@author Awais
*
*/

var DZHK = DZHK || {};

/**
*Generic Super Answer Class to inherit from
*more like an abstract class
*
*@constructor
*@param Fhir question object
*
*/
DZHK.Answer=function(question){
	this.question=question;
};

DZHK.Answer.prototype.question={};

/**
* To generate html for the response.
* @return string html for response interaction
*/
DZHK.Answer.prototype.generateUI=function(){
	return "
:)
";
};

/**
*use it to save different type of answers
*/
DZHK.Answer.prototype.saveAnswer=function(){
	alert("Implement a sub class");
};

/**
*to render the ui, adding listeners and saving response collected
*
*/
DZHK.Answer.prototype.render=function(selector){
	$(selector).html("default Render:"+this.generateUI());
};

DZHK.Answer.prototype.haveSubGroup=function(){
	if(this.question.group){
		return true;
	}
	return false;
}

DZHK.Answer.prototype.haveReferenceToValueSet=function(){
	if(this.question.options){
			return true;
	}
	return false;
}

DZHK.Answer.prototype.parseExtension=function(){
	var self=this;
	var ext={
		type:null,
		code:"",
		orientation:"vertical" //default Orientation;
	};

	try{
		if(this.question.extension && this.question.extension.length>0){
			for (var i = this.question.extension.length - 1; i >= 0; i--) {
				//this.question.extension[i]
				var type=this.checkExtensionFromUrl(this.question.extension[i]);
				if(type=="questionnaire-questionControl"){
					ext.type=type;
					ext.code=this.question.extension[i].valueCodeableConcept.coding[0].code;
				}else if(type=="questionnaire-choiceOrientation"){
					ext.orientation=this.question.extension[i].valueCode;
				}
			}
		}else{
			console.log("no extension found");
		}
	}catch(ex){
		console.error("problem parsing extension for question linkId"+self.question.linkId);
	}
	return ext;

};
DZHK.Answer.prototype.checkExtensionFromUrl=function(extension){

	if(typeof extension.url == "string"){
		return extension.url.substr(extension.url.lastIndexOf("/")+1,extension.url.length);
	}else{
		//undefined!
		return "undefined"
	}

};

DZHK.Answer.prototype.checkValueCodeableConcept=function(extension){
	if(typeof extension.valueCodeableConcept == "object"){
		return true;
	}else{
		return false;
	}
};

/**
* Sub classes for each specific type
* TextAnswer will generate TextArea
*/

DZHK.TextAnswer=function(){};
DZHK.TextAnswer=function(question){
	this.question=question;
};
DZHK.TextAnswer.prototype=new DZHK.Answer;
DZHK.TextAnswer.prototype.constructor=new DZHK.Answer;
DZHK.TextAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<textarea class='form-control' rows='3' placeholder='Enter ...'></textarea>"+
                "
"+
            "
";
    return html;
};
DZHK.TextAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" textarea");
	$(input).change(function(){
		self.question.answer={
			"valueText":$(this).val()
		}
	});
};

DZHK.DateAnswer=function(question){
	this.question=question;
};
DZHK.DateAnswer.prototype=new DZHK.Answer;
DZHK.DateAnswer.prototype.constructor=new DZHK.Answer;
DZHK.DateAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control' />"+
                    ""+
                        ""+
                    ""+
                "
"+
            "
";
    return html;
};
DZHK.DateAnswer.prototype.render=function(selector){
	var that=this;
	$(selector).html(this.generateUI());
	//initiate datetimepicker
	var answerDatePicker=$(selector+" #answer-"+this.question.linkId).datetimepicker({
		locale: 'de',
		format: 'L'
	});

	//save answer
	$(answerDatePicker).on("dp.change",function(e){
		that.question.answer={
			"valueDate":e.date.format("L")
		}
	});
};

DZHK.DateTimeAnswer=function(question){
	this.question=question;
};
DZHK.DateTimeAnswer.prototype=new DZHK.Answer;
DZHK.DateTimeAnswer.prototype.constructor=new DZHK.Answer;
DZHK.DateTimeAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control' />"+
                    ""+
                        ""+
                    ""+
                "
"+
            "
";
    return html;
};
DZHK.DateTimeAnswer.prototype.render=function(selector){
	var that=this;
	$(selector).html(this.generateUI());
	//initiate datetimepicker
	var answerDatePicker=$(selector+" #answer-"+this.question.linkId).datetimepicker({
		sideBySide:true,
		locale: 'de'
	});

	//save answer
	$(answerDatePicker).on("dp.change",function(e){
		that.question.answer={
			"valueDateTime":e.date.format() //(ISO 8601)
		}
	});
};

/**
*	IntegerAnswer Class
*/
DZHK.IntegerAnswer=function(question){
	this.question=question;
};
DZHK.IntegerAnswer.prototype=new DZHK.Answer;
DZHK.IntegerAnswer.prototype.constructor=new DZHK.Answer;
DZHK.IntegerAnswer.prototype.generateUI=function(){
	var html=
			"
"+
                "
"+
                    "<input type='text' class='form-control'/>"+
                "
"+
            "
";
    return html;
};
DZHK.IntegerAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" input");
	$(input).change(function(){
		self.question.answer={
			"valueInteger":$(this).val()
		}
	});
};

/**
*	StringAnswer Class inherited from integer
*/
DZHK.StringAnswer=function(question){
	this.question=question;
};
DZHK.StringAnswer.prototype=new DZHK.IntegerAnswer;
DZHK.StringAnswer.prototype.constructor=new DZHK.IntegerAnswer;
//can use integerClass generate ui function, validation may differ TODO: add validations later, if required
DZHK.IntegerAnswer.prototype.render=function(selector){
	var self=this;
	$(selector).html(this.generateUI());
	var input=$(selector+" #answer-"+this.question.linkId+" input");
	$(input).change(function(){
		self.question.answer={
			"valueString":$(this).val()
		}
	});
};

/**
*	ChoiceAnswer Class inherited from Answer
*/
DZHK.ChoiceAnswer=function(question){
	this.question=question;
};
DZHK.ChoiceAnswer.prototype=new DZHK.Answer;
DZHK.ChoiceAnswer.prototype.constructor=new DZHK.Answer;

DZHK.ChoiceAnswer.prototype.generateUI=function(ext){

	var html="";
	if(ext.type=="questionnaire-questionControl"){
		if(ext.code=="radio-button"){
				html= "
";
					for (var i = 0; i < this.question.option.length; i++) {
						html+="";
						}else{
							html+=" >"
							br="
"
						}
						html+="<input type='radio' name='iCheck' value='"+this.question.option[i].code+"'/> "+
						this.question.option[i].display+
						""+br;
					}
				html+="
";
		}else if(ext.code=="check-box"){
			//more or less same.
			html= "
";
					for (var i = 0; i < this.question.option.length; i++) {
						html+="";
						}else{
							html+=" >"
							br="
"
						}
						html+="<input type='checkbox' name='iCheck' value='"+this.question.option[i].code+"'/> "+
						this.question.option[i].display+
						""+br;
					}
				html+="
";

		}else{
			html="unsupported! questioncontrol extension type";
		}
	}
	return html;
}

DZHK.ChoiceAnswer.prototype.render=function(selector){
	// have to check options
	var self= this;

	this.question.answer=[];

	//check extensions
	var ext=this.parseExtension();

	if(ext.type){
		$(selector).html(this.generateUI(ext));

		if(ext.type=="questionnaire-questionControl" && ext.code=="radio-button"){
			$(selector+" #answer-"+this.question.linkId+" input[type='radio']").iCheck({
				radioClass: 'iradio_flat-blue'
			}).on("ifClicked",function(event){
				//answer=this.value;
				//store the answer;
				var ans=this.value;
				self.question.answer={
					"code":ans,
					"display":$(this).parent().parent().text().trim()
				};
			});
		}else if(ext.type=="questionnaire-questionControl" && ext.code=="check-box"){
			$(selector+" #answer-"+this.question.linkId+" input[type='checkbox']").iCheck({
				checkboxClass: 'icheckbox_flat-blue'
			}).on("ifChecked",function(event){
				//answer=this.value;

				var ans=this.value;
				 var answer={
				 	code:ans,
				 	display:$(this).parent().parent().text().trim()
				 };
				self.question.answer.push(answer);
			}).on("ifUnchecked",function(event){
				 var answer={
				 	code:this.value,
				 	display:$(this).parent().parent().text().trim()
				 };
				self.removeCheckBoxAnswer(answer);
			});
		}
	}else{
		//console.error("unsupported type!");
	}

};

DZHK.ChoiceAnswer.prototype.containsGroup=function(){
	console.error("not implemented yet: contains-Group");
};

DZHK.ChoiceAnswer.prototype.removeCheckBoxAnswer=function(answer){
	//improved
	for (var i = this.question.answer.length - 1; i >= 0; i--) {
		if (this.question.answer[i].code == answer.code) {
           this.question.answer.splice(i,1);
        }
	}
};

DZHK.ChoiceAnswer.prototype.containsOptionsReference=function(){
	console.error("not implemented yet: contains reference to valueset");
};

/**
*	OpenChoiceAnswer Class inherited from ChoiceAnswer
*/
DZHK.OpenChoiceAnswer=function(question){
	this.question=question;
};
DZHK.OpenChoiceAnswer.prototype=new DZHK.ChoiceAnswer;
DZHK.OpenChoiceAnswer.prototype.constructor=new DZHK.ChoiceAnswer;
DZHK.OpenChoiceAnswer.prototype.render=function(selector){
	//DZHK.Answer.prototype.render.call(this,selector);

	var self= this;

	this.question.answer=[];

	//check extensions
	var ext=this.parseExtension();
	if(this.question.group){
		if(this.question.options){
			this.containsOptionsReference();
		}
		this.containsGroup();
	}else{
		if(ext.type){
			$(selector).html(this.generateUI(ext));

			var otherHtml="
<input type='text' id='input-other' class='form-control' placeholder='other' disabled>
";

			$(selector+" #answer-"+this.question.linkId).append(otherHtml);

			$(selector+" #answer-"+self.question.linkId+" #input-other").change(function(){
				self.question.answer[1]={
					"valueString":$(this).val()
				};
			});

			if(ext.type=="questionnaire-questionControl" && ext.code=="radio-button"){
				$(selector+" #answer-"+this.question.linkId+" input[type='radio']").iCheck({
					radioClass: 'iradio_flat-blue'
				}).on("ifClicked",function(event){
					//store the answer;
					var ans=this.value;
					if(ans=="other"){
						$(selector+" #answer-"+self.question.linkId+" #input-other").prop('disabled', false);

					}else{
						$(selector+" #answer-"+self.question.linkId+" #input-other").prop('disabled', true);
					}

					self.question.answer=[{
							"code":ans,
							"display":$(this).parent().parent().text().trim()
					}];
				});
			}else if(ext.type=="questionnaire-questionControl" && ext.code=="check-box"){
				console.error("Not Implemented! openchoice with checkboxes?");
				//TODO: openchoice can be with checkbox?

				/*$(selector+" #answer-"+this.question.linkId+" input[type='checkbox']").iCheck({
					checkboxClass: 'icheckbox_flat-blue'
				}).on("ifChecked",function(event){
					//answer=this.value;
					var ans=this.value;
					 var answer={
					 	code:ans,
					 	display:$(this).parent().parent().text().trim()
					 };
					self.question.answer.push(answer);
				}).on("ifUnchecked",function(event){
					 var answer={
					 	code:this.value,
					 	display:$(this).parent().parent().text().trim()
					 };
					self.removeCheckBoxAnswer(answer);
				});*/
			}
		}else{
			//console.error("unsupported type!");
		}
	}

};

/**
* factory to generate answer type objects
*factory pattern;
*/
DZHK.AnswerFactory=function(){};
DZHK.AnswerFactory.prototype.answerClass=DZHK.StringAnswer;
DZHK.AnswerFactory.prototype.createAnswerClass=function(question){
	switch(question.type){
		case "date":
			this.answerClass=DZHK.DateAnswer;
			break;
		case "dateTime":
			this.answerClass=DZHK.DateTimeAnswer;
			break;
		case "integer":
			this.answerClass=DZHK.IntegerAnswer;
			break;
		case "text":
			this.answerClass=DZHK.TextAnswer;
			break;
		case "string":
			this.answerClass=DZHK.StringAnswer;
			break;
		case "choice":
			this.answerClass=DZHK.ChoiceAnswer;
			break;
		case "open-choice":
			this.answerClass=DZHK.OpenChoiceAnswer;
			break;
		default:
			console.error("unsupported answer type:"+question.type);
	}
	return new this.answerClass(question);
};
<|endoftext|>


<commit_before>// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;

server.listen(port, function () {
  console.log('Server listening at port %d', port);
});

// Routing
app.use(express.static(__dirname + '/public'));

// Chatroom

// usernames which are currently connected to the chat
var usernames = {};
var currentUserId = 0;
var screen;

io.on('connection', function (socket) {
  socket.on('screen', function () {
    screen = socket;
    console.log('Screen has joined');
  });

  // when the client emits 'add user', this listens and executes
  socket.on('user join', function () {
    // add the client's username to the global list
    usernames[currentUserId] = currentUserId;
    console.log('user join', currentUserId)
    io.sockets.emit('user joined', {
      newUserId: currentUserId
    });
    ++currentUserId;
  });

  socket.on('user input', function (data) {
    screen.emit('user input', data);
  });
});
<commit_msg>Handle user disconnect<commit_after>// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;

server.listen(port, function () {
  console.log('Server listening at port %d', port);
});

// Routing
app.use(express.static(__dirname + '/public'));

// Chatroom

// usernames which are currently connected to the chat
var usernames = {};
var currentUserId = 0;
var screen;

io.on('connection', function (socket) {
  socket.on('screen', function () {
    screen = socket;
    console.log('Screen has joined');
  });

  // when the client emits 'add user', this listens and executes
  socket.on('user join', function () {
    // add the client's username to the global list
    usernames[currentUserId] = currentUserId;
    socket.currentUserId = currentUserId;
    console.log('user join', currentUserId)
    io.sockets.emit('user joined', {
      newUserId: currentUserId
    });
    ++currentUserId;
  });

  socket.on('user input', function (data) {
    screen.emit('user input', data);
  });

  socket.on('disconnect', function () {
    // remove the username from global usernames list
    delete usernames[socket.currentUserId];
  });
});
<|endoftext|>


<commit_before>import { RENDERER_SUFFIX } from './constants';
import contentRendererMixin from './mixin';

export default {
  mixins: [contentRendererMixin],
  methods: {
    /**
     * @public
     */
    checkAnswer() {
      if (this.$refs.contentView && this.$refs.contentView.checkAnswer) {
        return this.$refs.contentView.checkAnswer();
        /* eslint-disable no-console */
      } else if (!this.$refs.contentView) {
        console.warn('No content view to check answer of');
      } else if (!this.$refs.contentView.checkAnswer) {
        console.warn('This content renderer has not implemented the checkAnswer method');
        /* eslint-enable */
      }
      this.registerContentActivity();
      return null;
    },
  },
  render: function(createElement) {
    if (this.canRenderContent(this.defaultItemPreset)) {
      const listeners = {
        ...this.$listeners,
      };
      contentRendererMixin.interactionEvents.forEach(event => {
        if (listeners[event]) {
          listeners[event] = [listeners[event], this.registerContentActivity];
        } else {
          listeners[event] = this.registerContentActivity;
        }
      });
      return createElement(this.defaultItemPreset + RENDERER_SUFFIX, {
        props: this.$props,
        on: listeners,
        ref: 'contentView',
      });
    }
    return createElement('ContentRendererError');
  },
};
<commit_msg>Pass attrs through to content renderers.<commit_after>import { RENDERER_SUFFIX } from './constants';
import contentRendererMixin from './mixin';

export default {
  mixins: [contentRendererMixin],
  methods: {
    /**
     * @public
     */
    checkAnswer() {
      if (this.$refs.contentView && this.$refs.contentView.checkAnswer) {
        return this.$refs.contentView.checkAnswer();
        /* eslint-disable no-console */
      } else if (!this.$refs.contentView) {
        console.warn('No content view to check answer of');
      } else if (!this.$refs.contentView.checkAnswer) {
        console.warn('This content renderer has not implemented the checkAnswer method');
        /* eslint-enable */
      }
      this.registerContentActivity();
      return null;
    },
  },
  render: function(createElement) {
    if (this.canRenderContent(this.defaultItemPreset)) {
      const listeners = {
        ...this.$listeners,
      };
      contentRendererMixin.interactionEvents.forEach(event => {
        if (listeners[event]) {
          listeners[event] = [listeners[event], this.registerContentActivity];
        } else {
          listeners[event] = this.registerContentActivity;
        }
      });
      return createElement(this.defaultItemPreset + RENDERER_SUFFIX, {
        props: this.$props,
        attrs: this.$attrs,
        on: listeners,
        ref: 'contentView',
      });
    }
    return createElement('ContentRendererError');
  },
};
<|endoftext|>


<commit_before>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community 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.osedu.org/licenses/ECL-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.
 */

define(['jquery', 'underscore', 'oae/api/oae.core', 'jquery-plugins/imgareaselect/jquery.imgareaselect'], function($, _, oae) {

    return function(uid, showSettings) {

        //////////////////////
        // Config Variables //
        //////////////////////

        var picture = false;
        var ratio = 1;
        var imageareaobject;
        var id = null;
        var fullPicHeight = 300;
        var fullPicWidth = 325;

        // These values are just in case there are no css values specified.
        // If you want to change the size of a thumbnail please do this in the CSS.
        var thumbnailWidth = 100;
        var thumbnailHeight = 100;

        // The modal object we'll show.
        var modal = null;

        // The type of principal we're dealing with (user or group.)
        var type = 'user';
        var principalData = null;

        //////////////
        // CSS IDS  //
        //////////////

        var containerTrigger = '#changepic_container_trigger'; // This is the id that will trigger this widget.

        // others
        var selectContentArea = '#changepic_selectpicture';
        var container = '#changepic_container';
        var picForm = '#changepic_form';
        var picInput = '#profilepicture';
        var picInputError = '#changepic_nofile_error';
        var uploadProcessing = '#changepic_uploading';
        var uploadNewButtons = '#changepic_uploadnew_buttons';
        var uploadNewCancel = '#profile_upload_cancel';
        var pictureMeasurer = '#picture_measurer';
        var pictureMeasurerImage = '#picture_measurer_image';
        var saveNewSelection = '#save_new_selection';
        var fullPicture = '#changepic_fullpicture_img';
        var fullPictureSpan = '#changepic_fullpicture';
        var thumbnail = '#thumbnail_img';
        var thumbnailSpan = '#thumbnail';
        var thumbnailContainer = '#thumbnail_container';
        var picInputErrorClass = 'changepic_input_error';

        // An array with selectors pointing to images that need to be changed.
        var imagesToChange = ['.oae-entity-picture-image img'];

        ///////////////////
        // UTIL FUNCTIONS //
        ///////////////////

         /**
         * Hides and reset image select area
         */
        var hideSelectArea = function() {
            if (imageareaobject) {
                imageareaobject.setOptions({
                    'hide': true,
                    'disable': true
                });
                imageareaobject.update();
            }

            $(selectContentArea).hide();
            $(uploadNewCancel).show();
        };

         /**
         * Shows image select area
         */
        var showSelectArea = function() {
            $(uploadNewCancel).hide();
            $(selectContentArea).show();
        };

        /**
         * When the user has drawn a square this function will be called by imgAreaSelect.
         * This will draw the thumbnail by modifying it's css values.
         *
         * @param {Object} img    The thumbnail
         * @param {Object} selection The selection object from imgAreaSelect
         */
        var preview = function(img, selection) {
            // How much has the user scaled down the image?
            var scaleX = thumbnailWidth / (selection.width || 1);
            var scaleY = thumbnailHeight / (selection.height || 1);

            // Change the thumbnail according to the user his selection via CSS.
            $(thumbnail).css({
                'width': Math.round(scaleX * img.width) + 'px',
                'height': Math.round(scaleY * img.height) + 'px',
                'marginLeft': '-' + Math.round(scaleX * selection.x1) + 'px',
                'marginTop': '-' + Math.round(scaleY * selection.y1) + 'px'
            });
        };

        /**
         * Shows file input error
         */
        var showInputError = function() {
            $(picInputError).show();
            $(picInput).addClass(picInputErrorClass);
            if ($(selectContentArea + ':visible') && imageareaobject) {
                imageareaobject.update();
            }
        };

        /**
         * Hides file input error
         */
        var hideInputError = function() {
            $(picInputError).hide();
            $(picInput).removeClass(picInputErrorClass);
            if ($(selectContentArea + ':visible') && imageareaobject) {
                imageareaobject.update();
            }
        };

         /**
         * Empty upload field by resetting the form
         */
        var resetUploadField = function() {
            $(picForm)[0].reset();
            $(picForm).attr('action', '/api/' + type + '/' + id + '/picture');
            hideInputError();
            $(uploadProcessing).hide();
            $(uploadNewButtons).show();
            $('#profile_upload').attr('disabled', 'disabled');
        };

        // Add click event to all cancel buttons in the overlay
        // Since file upload form is reset every time overlay closes do this in init function
        $('#changepic_container .jqmClose').click(function() {
            resetUploadField();
        });

        /**
         * On changepic form submit, check that a file has been selected
         * and submit the form.
         */
        $('#profile_upload').off('click').on('click', function() {
            // validate args
            // file extension allow for image
            var extensionArray = ['.png', '.jpg', '.jpeg', '.gif', '.bmp'];
            // get file name
            var fileName = $(picInput).val();
            // get extension from the file name.
            var extension = fileName.slice(fileName.lastIndexOf('.')).toLowerCase();
            var allowSubmit = _.indexOf(extensionArray, extension) > -1;

            // if image format is acceptable
            if (allowSubmit) {
                // Hide the form.
                hideInputError();
                $(uploadNewButtons).hide();
                hideSelectArea();

                // Show a processing image.
                $(uploadProcessing).show();

                // Submit the form.
                $(picForm).ajaxForm({
                    'success': function(data) {
                        // We get the updated principal back from the API.
                        // Update our local data and re-render the modal.
                        principalData = data;
                        doInit();
                    },
                    'error': function() {
                        showInputError();
                        return false;
                    }
                });
                $(picForm).submit();
            } else {
                // no input, show error
                showInputError();
            }
        });

        /**
         * Initialize function that will display the correct part of the form.
         */
        var doInit = function() {
            hideSelectArea();

            // If the image is freshly uploaded then reset the imageareaobject to reset all values on init
            if (!principalData.smallPicture) {
                imageareaobject = null;
            }

            // Get the preferred size for the thumbnail.
            var prefThumbWidth = parseInt($(thumbnailContainer).css('width').replace(/px/gi,''), 10);
            var prefThumbHeight = parseInt($(thumbnailContainer).css('height').replace(/px/gi,''), 10);

            // Make sure we don't have 0
            thumbnailWidth  = (prefThumbWidth > 0) ? prefThumbWidth : thumbnailWidth;
            thumbnailHeight  = (prefThumbHeight > 0) ? prefThumbHeight : thumbnailHeight;

            if (principalData.largePicture) {
                // Set the unvisible image to the full blown image.
                $(pictureMeasurer).html('');

                // Check the current picture's size
                $(pictureMeasurerImage).on('load', function(ev) {
                    resetUploadField();

                    // Get the actual sizes
                    var realw = $(pictureMeasurerImage).width();
                    var realh = $(pictureMeasurerImage).height();

                    // Set the images
                    $(fullPictureSpan).html('');
                    $(thumbnailSpan).html('');

                    // Reset ratio
                    ratio = 1;

                    // fullPicWidth (500) and fullPicHeight (300) set in config variables
                    // Width < 500 ; Height < 300 => set the original height and width
                    if (realw < fullPicWidth && realh < fullPicHeight) {
                        $(fullPicture).width(realw);
                        $(fullPicture).height(realh);

                    // Width > 500 ; Height < 300 => Width = 500
                    } else if (realw > fullPicWidth && (realh / (realw / fullPicWidth) < fullPicHeight)) {
                        ratio = realw / fullPicWidth;
                        $(fullPicture).width(fullPicWidth);
                        $(fullPicture).height(Math.floor(realh / ratio));

                    // Width < 500 ; Height > 300 => Height = 300
                    } else if (realh > fullPicHeight && (realw / (realh / fullPicHeight) < fullPicWidth)) {
                        ratio = realh / fullPicHeight;
                        $(fullPicture).height(fullPicHeight);
                        $(fullPicture).width(Math.floor(realw / ratio));

                    // Width > 500 ; Height > 300
                    } else if (realh > fullPicHeight && (realw / (realh / fullPicHeight) > fullPicWidth)) {

                        var heightonchangedwidth = realh / (realw / fullPicWidth);
                        if (heightonchangedwidth > fullPicHeight) {
                            ratio = realh / fullPicHeight;
                            $(fullPicture).height(fullPicHeight);
                        } else {
                            ratio = realw / fullPicWidth;
                            $(fullPicture).width(fullPicWidth);
                        }
                    }

                    // The initial selection is the biggest possible square we can squeeze out of the picture.
                    var size = (realw > realh) ? realh : realw;
                    var startSelection = {
                        'x1': 0,
                        'y1': 0,
                        'x2': size,
                        'y2': size,
                        'width': size,
                        'height': size
                    };

                    // Set the imgAreaSelect to a function so we can access it later on
                    imageareaobject = $(fullPicture).imgAreaSelect({
                        'aspectRatio': '1:1',
                        'enable': true,
                        'show': true,
                        'instance': true,
                        'onInit': function() {
                            // Show a "preview" of the cropped image, if we crop the biggest square out of the big image.
                            preview($(pictureMeasurerImage)[0], startSelection);

                            // Make that selection
                            imageareaobject.setOptions({'show': true, 'enable': true});
                            imageareaobject.update();
                        },
                        'onSelectChange': preview
                    });
                    showSelectArea();
                });

                // if there is upload error show the error message
                $(pictureMeasurerImage).on('error', function() {
                    showInputError();
                });
            }
        };

        // Remove error notification when a new file is chosen
        $(picInput).on('change', function() {
            hideInputError();
            $('#profile_upload').removeAttr('disabled');
        });

        // This is the function that will be called when a user has cut out a selection
        // and saves it.
        $(saveNewSelection).click(function(ev) {
            var userSelection = imageareaobject.getSelection();
            cropPicture(userSelection);
        });

        /**
         * Crops the picture
         *
         * @param {Object} userSelection  The object that determines how the image should be cropped.
         * @param {Number} userSelection.x The top left x coordinate.
         * @param {Number} userSelection.y The top left x coordinate.
         * @param {Number} userSelection.width The size of the square that should be cropped out.
         */
        var cropPicture = function(userSelection) {
            // The parameters for the cropit service.
            var data = {
                'x': Math.floor(userSelection.x1 * ratio),
                'y': Math.floor(userSelection.y1 * ratio),
                'width': Math.floor(userSelection.width * ratio),
                'principalId': id
            };

            if (data.width === 0 || data.height === 0) {
                data.width = $(fullPicture).width();
                data.height = $(fullPicture).height();
                data.x = 0;
                data.y = 0;
            }

            // Post all of this to the server
            $.ajax({
                'url': '/api/crop',
                'type': 'POST',
                'data': data,
                success: function(data) {
                    // The crop API returns the updated principal.
                    principalData = data;

                    // Change all the pictures on the page.
                    for (var i = 0; i < imagesToChange.length;i++) {
                        $(imagesToChange[i]).attr('src', data.smallPicture);
                    }

                    // Hide the layover.
                    modal.close();
                },
                error: function(xhr, textStatus, thrownError) {
                    oae.api.util.showNotification(oae.api.i18n.translate('__MSG__AN_ERROR_HAS_OCCURRED__'), textStatus, 'error');
                }
            });

        };

        ////////////////////////////
        // jQuery Modal functions //
        ////////////////////////////

        /**
         * Hide the layover
         * @param {Object} hash the object that represents the layover
         */
        var hideArea = function(hash) {
            // Remove the selecting of an area on an image.
            if (imageareaobject) {
                imageareaobject.setOptions({
                    'hide': true,
                    'disable': true
                });
                imageareaobject.update();
            }

            hash.w.hide();
            hash.o.remove();
        };

        /**
         * Show the layover.
         * @param {Object} hash
         */
        var showArea = function(hash) {
            resetUploadField();
            doInit();
            hash.w.show();
        };

        modal = oae.api.util.modal(container, {
            'onHide': hideArea,
            'onShow': showArea
        });

        $(document).on('init.changepic.sakai', function(ev, data) {
            type = data.type;
            principalData = data.data;
            id = (type === 'user') ? principalData.userId : principalData.groupId;
            modal.open();
        });
    };
});
<commit_msg>Data is not passed by reference, sticking the new pictures on the global me object.<commit_after>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community 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.osedu.org/licenses/ECL-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.
 */

define(['jquery', 'underscore', 'oae/api/oae.core', 'jquery-plugins/imgareaselect/jquery.imgareaselect'], function($, _, oae) {

    return function(uid, showSettings) {

        //////////////////////
        // Config Variables //
        //////////////////////

        var picture = false;
        var ratio = 1;
        var imageareaobject;
        var id = null;
        var fullPicHeight = 300;
        var fullPicWidth = 325;

        // These values are just in case there are no css values specified.
        // If you want to change the size of a thumbnail please do this in the CSS.
        var thumbnailWidth = 100;
        var thumbnailHeight = 100;

        // The modal object we'll show.
        var modal = null;

        // The type of principal we're dealing with (user or group.)
        var type = 'user';
        var principalData = null;

        //////////////
        // CSS IDS  //
        //////////////

        var containerTrigger = '#changepic_container_trigger'; // This is the id that will trigger this widget.

        // others
        var selectContentArea = '#changepic_selectpicture';
        var container = '#changepic_container';
        var picForm = '#changepic_form';
        var picInput = '#profilepicture';
        var picInputError = '#changepic_nofile_error';
        var uploadProcessing = '#changepic_uploading';
        var uploadNewButtons = '#changepic_uploadnew_buttons';
        var uploadNewCancel = '#profile_upload_cancel';
        var pictureMeasurer = '#picture_measurer';
        var pictureMeasurerImage = '#picture_measurer_image';
        var saveNewSelection = '#save_new_selection';
        var fullPicture = '#changepic_fullpicture_img';
        var fullPictureSpan = '#changepic_fullpicture';
        var thumbnail = '#thumbnail_img';
        var thumbnailSpan = '#thumbnail';
        var thumbnailContainer = '#thumbnail_container';
        var picInputErrorClass = 'changepic_input_error';

        // An array with selectors pointing to images that need to be changed.
        var imagesToChange = ['.oae-entity-picture-image img'];

        ///////////////////
        // UTIL FUNCTIONS //
        ///////////////////

         /**
         * Hides and reset image select area
         */
        var hideSelectArea = function() {
            if (imageareaobject) {
                imageareaobject.setOptions({
                    'hide': true,
                    'disable': true
                });
                imageareaobject.update();
            }

            $(selectContentArea).hide();
            $(uploadNewCancel).show();
        };

         /**
         * Shows image select area
         */
        var showSelectArea = function() {
            $(uploadNewCancel).hide();
            $(selectContentArea).show();
        };

        /**
         * When the user has drawn a square this function will be called by imgAreaSelect.
         * This will draw the thumbnail by modifying it's css values.
         *
         * @param {Object} img    The thumbnail
         * @param {Object} selection The selection object from imgAreaSelect
         */
        var preview = function(img, selection) {
            // How much has the user scaled down the image?
            var scaleX = thumbnailWidth / (selection.width || 1);
            var scaleY = thumbnailHeight / (selection.height || 1);

            // Change the thumbnail according to the user his selection via CSS.
            $(thumbnail).css({
                'width': Math.round(scaleX * img.width) + 'px',
                'height': Math.round(scaleY * img.height) + 'px',
                'marginLeft': '-' + Math.round(scaleX * selection.x1) + 'px',
                'marginTop': '-' + Math.round(scaleY * selection.y1) + 'px'
            });
        };

        /**
         * Shows file input error
         */
        var showInputError = function() {
            $(picInputError).show();
            $(picInput).addClass(picInputErrorClass);
            if ($(selectContentArea + ':visible') && imageareaobject) {
                imageareaobject.update();
            }
        };

        /**
         * Hides file input error
         */
        var hideInputError = function() {
            $(picInputError).hide();
            $(picInput).removeClass(picInputErrorClass);
            if ($(selectContentArea + ':visible') && imageareaobject) {
                imageareaobject.update();
            }
        };

         /**
         * Empty upload field by resetting the form
         */
        var resetUploadField = function() {
            $(picForm)[0].reset();
            $(picForm).attr('action', '/api/' + type + '/' + id + '/picture');
            hideInputError();
            $(uploadProcessing).hide();
            $(uploadNewButtons).show();
            $('#profile_upload').attr('disabled', 'disabled');
        };

        // Add click event to all cancel buttons in the overlay
        // Since file upload form is reset every time overlay closes do this in init function
        $('#changepic_container .jqmClose').click(function() {
            resetUploadField();
        });

        /**
         * On changepic form submit, check that a file has been selected
         * and submit the form.
         */
        $('#profile_upload').off('click').on('click', function() {
            // validate args
            // file extension allow for image
            var extensionArray = ['.png', '.jpg', '.jpeg', '.gif', '.bmp'];
            // get file name
            var fileName = $(picInput).val();
            // get extension from the file name.
            var extension = fileName.slice(fileName.lastIndexOf('.')).toLowerCase();
            var allowSubmit = _.indexOf(extensionArray, extension) > -1;

            // if image format is acceptable
            if (allowSubmit) {
                // Hide the form.
                hideInputError();
                $(uploadNewButtons).hide();
                hideSelectArea();

                // Show a processing image.
                $(uploadProcessing).show();

                // Submit the form.
                $(picForm).ajaxForm({
                    'success': function(data) {
                        // We get the updated principal back from the API.
                        // Update the global me object.
                        if (type === 'user') {
                            oae.data.me.largePicture = data.largePicture;
                        }
                        doInit();
                    },
                    'error': function() {
                        showInputError();
                        return false;
                    }
                });
                $(picForm).submit();
            } else {
                // no input, show error
                showInputError();
            }
        });

        /**
         * Initialize function that will display the correct part of the form.
         */
        var doInit = function() {
            hideSelectArea();

            // If the image is freshly uploaded then reset the imageareaobject to reset all values on init
            if (!principalData.smallPicture) {
                imageareaobject = null;
            }

            // Get the preferred size for the thumbnail.
            var prefThumbWidth = parseInt($(thumbnailContainer).css('width').replace(/px/gi,''), 10);
            var prefThumbHeight = parseInt($(thumbnailContainer).css('height').replace(/px/gi,''), 10);

            // Make sure we don't have 0
            thumbnailWidth  = (prefThumbWidth > 0) ? prefThumbWidth : thumbnailWidth;
            thumbnailHeight  = (prefThumbHeight > 0) ? prefThumbHeight : thumbnailHeight;

            if (principalData.largePicture) {
                console.log('doInit: %s', principalData.largePicture);
                // Set the unvisible image to the full blown image.
                $(pictureMeasurer).html('');

                // Check the current picture's size
                $(pictureMeasurerImage).on('load', function(ev) {
                    resetUploadField();

                    // Get the actual sizes
                    var realw = $(pictureMeasurerImage).width();
                    var realh = $(pictureMeasurerImage).height();

                    // Set the images
                    $(fullPictureSpan).html('');
                    $(thumbnailSpan).html('');

                    // Reset ratio
                    ratio = 1;

                    // fullPicWidth (500) and fullPicHeight (300) set in config variables
                    // Width < 500 ; Height < 300 => set the original height and width
                    if (realw < fullPicWidth && realh < fullPicHeight) {
                        $(fullPicture).width(realw);
                        $(fullPicture).height(realh);

                    // Width > 500 ; Height < 300 => Width = 500
                    } else if (realw > fullPicWidth && (realh / (realw / fullPicWidth) < fullPicHeight)) {
                        ratio = realw / fullPicWidth;
                        $(fullPicture).width(fullPicWidth);
                        $(fullPicture).height(Math.floor(realh / ratio));

                    // Width < 500 ; Height > 300 => Height = 300
                    } else if (realh > fullPicHeight && (realw / (realh / fullPicHeight) < fullPicWidth)) {
                        ratio = realh / fullPicHeight;
                        $(fullPicture).height(fullPicHeight);
                        $(fullPicture).width(Math.floor(realw / ratio));

                    // Width > 500 ; Height > 300
                    } else if (realh > fullPicHeight && (realw / (realh / fullPicHeight) > fullPicWidth)) {

                        var heightonchangedwidth = realh / (realw / fullPicWidth);
                        if (heightonchangedwidth > fullPicHeight) {
                            ratio = realh / fullPicHeight;
                            $(fullPicture).height(fullPicHeight);
                        } else {
                            ratio = realw / fullPicWidth;
                            $(fullPicture).width(fullPicWidth);
                        }
                    }

                    // The initial selection is the biggest possible square we can squeeze out of the picture.
                    var size = (realw > realh) ? realh : realw;
                    var startSelection = {
                        'x1': 0,
                        'y1': 0,
                        'x2': size,
                        'y2': size,
                        'width': size,
                        'height': size
                    };

                    // Set the imgAreaSelect to a function so we can access it later on
                    imageareaobject = $(fullPicture).imgAreaSelect({
                        'aspectRatio': '1:1',
                        'enable': true,
                        'show': true,
                        'instance': true,
                        'onInit': function() {
                            // Show a "preview" of the cropped image, if we crop the biggest square out of the big image.
                            preview($(pictureMeasurerImage)[0], startSelection);

                            // Make that selection
                            imageareaobject.setOptions({'show': true, 'enable': true});
                            imageareaobject.update();
                        },
                        'onSelectChange': preview
                    });
                    showSelectArea();
                });

                // if there is upload error show the error message
                $(pictureMeasurerImage).on('error', function() {
                    showInputError();
                });
            }
        };

        // Remove error notification when a new file is chosen
        $(picInput).on('change', function() {
            hideInputError();
            $('#profile_upload').removeAttr('disabled');
        });

        // This is the function that will be called when a user has cut out a selection
        // and saves it.
        $(saveNewSelection).click(function(ev) {
            var userSelection = imageareaobject.getSelection();
            cropPicture(userSelection);
        });

        /**
         * Crops the picture
         *
         * @param {Object} userSelection  The object that determines how the image should be cropped.
         * @param {Number} userSelection.x The top left x coordinate.
         * @param {Number} userSelection.y The top left x coordinate.
         * @param {Number} userSelection.width The size of the square that should be cropped out.
         */
        var cropPicture = function(userSelection) {
            // The parameters for the cropit service.
            var data = {
                'x': Math.floor(userSelection.x1 * ratio),
                'y': Math.floor(userSelection.y1 * ratio),
                'width': Math.floor(userSelection.width * ratio),
                'principalId': id
            };

            if (data.width === 0 || data.height === 0) {
                data.width = $(fullPicture).width();
                data.height = $(fullPicture).height();
                data.x = 0;
                data.y = 0;
            }

            // Post all of this to the server
            $.ajax({
                'url': '/api/crop',
                'type': 'POST',
                'data': data,
                success: function(data) {
                    // Update the global me object.
                    if (type === 'user') {
                        oae.data.me.smallPicture = data.smallPicture;
                        oae.data.me.mediumPicture = data.mediumPicture;
                    }

                    // Change all the pictures on the page.
                    for (var i = 0; i < imagesToChange.length;i++) {
                        $(imagesToChange[i]).attr('src', data.smallPicture);
                    }

                    // Hide the layover.
                    modal.close();
                },
                error: function(xhr, textStatus, thrownError) {
                    oae.api.util.showNotification(oae.api.i18n.translate('__MSG__AN_ERROR_HAS_OCCURRED__'), textStatus, 'error');
                }
            });

        };

        ////////////////////////////
        // jQuery Modal functions //
        ////////////////////////////

        /**
         * Hide the layover
         * @param {Object} hash the object that represents the layover
         */
        var hideArea = function(hash) {
            // Remove the selecting of an area on an image.
            if (imageareaobject) {
                imageareaobject.setOptions({
                    'hide': true,
                    'disable': true
                });
                imageareaobject.update();
            }

            hash.w.hide();
            hash.o.remove();
        };

        /**
         * Show the layover.
         * @param {Object} hash
         */
        var showArea = function(hash) {
            resetUploadField();
            doInit();
            hash.w.show();
        };

        modal = oae.api.util.modal(container, {
            'onHide': hideArea,
            'onShow': showArea
        });

        $(document).on('init.changepic.sakai', function(ev, data) {
            type = data.type;
            principalData = data.data;
            console.log('init.changepic.sakai');
            console.log(data);
            id = (type === 'user') ? principalData.userId : principalData.groupId;
            modal.open();
        });
    };
});
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import AppLoadingScreen from './AppLoadingScreen'

function assetUrl(staticPath, item) {
  const isAbsolute = item.path.match(/^https?:\/\//)
  if (isAbsolute) {
    return item.path
  }

  const base = `${staticPath}/${item.path}`
  if (!item.hash) {
    return base
  }

  const hasQuery = base.indexOf('?') !== -1
  const separator = hasQuery ? '&' : '?'
  return `${base}${separator}${item.hash}`
}

function Document(props) {
  const stylesheets = props.stylesheets.map(item =>
    <link
      key={item.path}
      rel="stylesheet"
      href={assetUrl(props.staticPath, item)}
    />
  )

  const scripts = props.scripts.map(item =>