<commit_before>'use strict';
/**
 * 消息解析和处理模块
 * @type {[type]}
 */

let moment = require('moment');
let mongodb = require('../libs/mongodb'),
	alias = require('../libs/alias'),
	apis = {
		email: require('../gateway/email'),
		wechat: require('../gateway/wechat'),
		app: require('../gateway/push'),
		sms: require('../gateway/sms')
	},
	events = require('../libs/events');
let _ = require('underscore');
const config = require('config');

module.exports = {
	// 获取用户信息 -todo aggregate wechat
	resolve (event) {

		return new Promise((resolve, reject) => {
			event = event.toObject();
			let param = event.param;

			let queryMessageSetting = {
				mids: [event.type]
			};
			const projectid = param.project || param.projectid;
			if(projectid){
				queryMessageSetting.projectid = projectid;
			}
			else{
				queryMessageSetting.projectid = 'PLT';
			}

			RPC.Message.Config.List(queryMessageSetting).then(
				result=>{
					if(result.code != ErrorCode.OK ){
						return reject(result);
					}

					if(_.isArray(result.result)){
						return reject(ErrorCode.ack(ErrorCode.NOTSUPPORT, result));
					}

					const setting = _.omit(result.result, ['mid', 'projectid']);
					MySQL.Account
						.findOne({
							where: {
								$or: [
									{uid: param.to || param.account || param.uid},
									{user: param.to || param.account || param.uid}
								],
								timedelete: 0
							},
							limit: 1
						})
						.then(
							user=>{
								if(!user){
									log.error(param, 'can not find');
								}
								else {
									resolve({
										target: MySQL.Plain(user),
										msg: event,
										setting: setting
									});
								}
							},
							err=>{
								reject(err);
							}
						);
				}
			);
		});
	},

	// 用户用户 APP tag
	getApp (event) {
		log.debug('get event for app: ', event);
	},

	// 获取微信信息
	getWechat (user, event, eventName) {
		let	param = event.param;
		// 根据 gateway 将数据传入 pipeline;

        return new Promise((resolve, reject) =>{
            MySQL.WXOpenIDUser
                .findAll({
                    where: {
                        user: user.user
                    }
                })
                .then(
                    result=>{
                        // log.debug('wechat user ', user, data);
						let wx = [];
						result.map(r=>{
							wx.push(MySQL.Plain(r));
						});

                        resolve(
                            {
                                gateway: 'wechat',
                                target: wx,
                                msg: {
                                    event: eventName,
                                    data: param
                                }
                            }
						);
                    },err=>{
                        log.error('wechat user get error: ', err, user);
                        reject(err);
                    }
                );
        });
        //
		// return getWechat(user)
		// 	.then((wx) => {
		// 		return {
		// 			gateway: 'wechat',
		// 			target: wx,
		// 			msg: {
		// 				event: eventName,
		// 				data: param
		// 			}
		// 		};
		// 	});
	},

	send (user, param, settings) {
		let destroy = true;
		// log.info('sending: ', user, ' params: ', param);
		param.param.user = user.user;

		if (!user) {
			throw new Error("User must not be null");
		}

		let type = param.type,
			eventName = alias[`event:${type}`],
			email = user.email;
		if(param.timestamp){
			param.param.time = param.timestamp;///moment.unix(param.timestamp).toDate();
		}

		_.map(settings, (enable, channel)=>{
			if(!enable){
				return;
			}

			switch(channel){
				case 'email':
                    this.pipeline('email', email, {
                        event: eventName,
                        template: event,
                        data: param
                    });
					break;
				case 'app':
                    this.pipeline('push', param, eventName);
					break;
				case 'sms':
                    let doc = Object.assign({}, param.param);
                    doc.mobile = user.mobile;
                    // 如果uid 不是 手机号 则不发送
                    this.pipeline('sms', doc, eventName);
					break;
				case 'wechat':
                    this.getWechat(user, param, eventName)
                        .then((data)=> {
                            try{
                                this.pipeline(data.gateway, data.target, data.msg);
                            }catch(e){
                                log.error('get wechat exception: ', e, param, eventName, data);
                            }
                        });
					break;

			}
		});

		return destroy;
	},

	pipeline (gateway, target, msg) {
		// log.warn('pipeline mesage : ', gateway, msg.event);

		if(config.debug){
			return log.debug(gateway, target, msg);
		}

		try{
			if(_.isArray(target)){
				target.forEach(v=>{
						let api = apis[gateway];
						return api.Send(v, msg);
					})
			}
			else{
				let api = apis[gateway];
				return api.Send(target, msg);
			}
		}catch(e){
			log.error('pipeline exception: ', e, gateway, target, msg);
		}
	},

	discard (event) {
		log.error('discard: ', event);
	}
};<commit_msg>修正RPC调用问题<commit_after>'use strict';
/**
 * 消息解析和处理模块
 * @type {[type]}
 */

let moment = require('moment');
let mongodb = require('../libs/mongodb'),
	alias = require('../libs/alias'),
	apis = {
		email: require('../gateway/email'),
		wechat: require('../gateway/wechat'),
		app: require('../gateway/push'),
		sms: require('../gateway/sms')
	},
	events = require('../libs/events');
let _ = require('underscore');
const config = require('config');

module.exports = {
	// 获取用户信息 -todo aggregate wechat
	resolve (event) {

		return new Promise((resolve, reject) => {
			event = event.toObject();
			let param = event.param;

			let queryMessageSetting = {
				mids: [event.type.toString()]
			};
			const projectid = param.project || param.projectid;
			if(projectid){
				queryMessageSetting.projectid = projectid;
			}
			else{
				queryMessageSetting.projectid = 'PLT';
			}

			RPC.Message.Config.List(queryMessageSetting).then(
				result=>{
					if(result.code != ErrorCode.OK ){
						return reject(result);
					}

					if(_.isArray(result.result)){
						return reject(ErrorCode.ack(ErrorCode.NOTSUPPORT, result));
					}

					const setting = _.omit(result.result, ['mid', 'projectid']);
					MySQL.Account
						.findOne({
							where: {
								$or: [
									{uid: param.to || param.account || param.uid},
									{user: param.to || param.account || param.uid}
								],
								timedelete: 0
							},
							limit: 1
						})
						.then(
							user=>{
								if(!user){
									log.error(param, 'can not find');
								}
								else {
									resolve({
										target: MySQL.Plain(user),
										msg: event,
										setting: setting
									});
								}
							},
							err=>{
								reject(err);
							}
						);
				}
			);
		});
	},

	// 用户用户 APP tag
	getApp (event) {
		log.debug('get event for app: ', event);
	},

	// 获取微信信息
	getWechat (user, event, eventName) {
		let	param = event.param;
		// 根据 gateway 将数据传入 pipeline;

        return new Promise((resolve, reject) =>{
            MySQL.WXOpenIDUser
                .findAll({
                    where: {
                        user: user.user
                    }
                })
                .then(
                    result=>{
                        // log.debug('wechat user ', user, data);
						let wx = [];
						result.map(r=>{
							wx.push(MySQL.Plain(r));
						});

                        resolve(
                            {
                                gateway: 'wechat',
                                target: wx,
                                msg: {
                                    event: eventName,
                                    data: param
                                }
                            }
						);
                    },err=>{
                        log.error('wechat user get error: ', err, user);
                        reject(err);
                    }
                );
        });
        //
		// return getWechat(user)
		// 	.then((wx) => {
		// 		return {
		// 			gateway: 'wechat',
		// 			target: wx,
		// 			msg: {
		// 				event: eventName,
		// 				data: param
		// 			}
		// 		};
		// 	});
	},

	send (user, param, settings) {
		let destroy = true;
		// log.info('sending: ', user, ' params: ', param);
		param.param.user = user.user;

		if (!user) {
			throw new Error("User must not be null");
		}

		let type = param.type,
			eventName = alias[`event:${type}`],
			email = user.email;
		if(param.timestamp){
			param.param.time = param.timestamp;///moment.unix(param.timestamp).toDate();
		}

		_.map(settings, (enable, channel)=>{
			if(!enable){
				return;
			}

			switch(channel){
				case 'email':
                    this.pipeline('email', email, {
                        event: eventName,
                        template: event,
                        data: param
                    });
					break;
				case 'app':
                    this.pipeline('push', param, eventName);
					break;
				case 'sms':
                    let doc = Object.assign({}, param.param);
                    doc.mobile = user.mobile;
                    // 如果uid 不是 手机号 则不发送
                    this.pipeline('sms', doc, eventName);
					break;
				case 'wechat':
                    this.getWechat(user, param, eventName)
                        .then((data)=> {
                            try{
                                this.pipeline(data.gateway, data.target, data.msg);
                            }catch(e){
                                log.error('get wechat exception: ', e, param, eventName, data);
                            }
                        });
					break;

			}
		});

		return destroy;
	},

	pipeline (gateway, target, msg) {
		// log.warn('pipeline mesage : ', gateway, msg.event);

		if(config.debug){
			return log.debug(gateway, target, msg);
		}

		try{
			if(_.isArray(target)){
				target.forEach(v=>{
						let api = apis[gateway];
						return api.Send(v, msg);
					})
			}
			else{
				let api = apis[gateway];
				return api.Send(target, msg);
			}
		}catch(e){
			log.error('pipeline exception: ', e, gateway, target, msg);
		}
	},

	discard (event) {
		log.error('discard: ', event);
	}
};<|endoftext|>


<commit_before>import { Alert, TrackUtils, StringUtils, igvxhr, SessionFileLoad } from '../../../node_modules/igv-widgets/dist/igv-widgets.js';
import ModalTable from '../../../node_modules/data-modal/js/modalTable.js';
import EncodeDataSource from '../../../node_modules/data-modal/js/encodeDataSource.js';
import hic from "../../../js/api.js";
import QRCode from "./qrcode.js";
import { allBrowsers } from './site.js';
import SessionController from "../../../js/sessionController.js";
import { toJSON } from "../../../js/init.js";

let googleEnabled = false;

let lastGenomeId = undefined;
let qrcode = undefined;
let currentContactMapDropdownButtonID = undefined;
let sessionController;

let $hic_share_url_modal;

const encodeModal = new ModalTable({ id: 'hic-encode-modal', title: 'ENCODE', selectHandler: selected => loadTracks(selected) });

const initializationHelper = async ($appContainer, config) => {

    const genomeChangeListener = {

        receiveEvent: async event => {

            const { data: genomeId } = event;
            if (lastGenomeId !== genomeId) {

                lastGenomeId = genomeId;

                if (config.trackMenu) {
                    let tracksURL = config.trackMenu.items.replace("$GENOME_ID", genomeId);
                    await loadAnnotationSelector($('#' + config.trackMenu.id), tracksURL, "1D");
                }

                if (config.trackMenu2D) {
                    let annotations2dURL = config.trackMenu2D.items.replace("$GENOME_ID", genomeId);
                    await loadAnnotationSelector($('#' + config.trackMenu2D.id), annotations2dURL, "2D");
                }

                if (EncodeDataSource.supportsGenome(genomeId)) {
                    $('#hic-encode-modal-button').show();
                    createEncodeTable(genomeId);
                } else {
                    $('#hic-encode-modal-button').hide();
                }
            }
        }
    };

    for (let browser of allBrowsers) {
        browser.eventBus.subscribe("GenomeChange", genomeChangeListener);
        browser.eventBus.subscribe("MapLoad", checkBDropdown);
        updateBDropdown(browser);
    }

    // Must manually trigger the genome change event on initial load
    if (hic.HICBrowser.currentBrowser && hic.HICBrowser.currentBrowser.genome) {
        await genomeChangeListener.receiveEvent({data: hic.HICBrowser.currentBrowser.genome.id})
    }

    // session file load config
    const sessionFileLoadConfig =
        {
            localFileInput: document.querySelector('#igv-app-dropdown-local-session-file-input'),
            dropboxButton: document.querySelector('#igv-app-dropdown-dropbox-session-file-button'),
            googleEnabled,
            googleDriveButton: document.querySelector('#igv-app-dropdown-google-drive-session-file-button'),
            loadHandler: config => hic.loadSession(config)
        };

    // Session Controller
    const sessionControllerConfig =
        {
            sessionLoadModal: document.querySelector('#igv-app-session-from-url-modal'),
            sessionSaveModal: document.querySelector('#igv-app-session-save-modal'),
            sessionFileLoad: new SessionFileLoad(sessionFileLoadConfig),
            JSONProvider: () => toJSON()
        };
    sessionController = new SessionController(sessionControllerConfig);

    if (config.mapMenu) {
        await populatePulldown(config.mapMenu);
    }

    $hic_share_url_modal = $('#hic-share-url-modal');

    $hic_share_url_modal.on('show.bs.modal', async function (e) {

        let href = new String(window.location.href);

        // This js file is specific to the aidenlab site, and we know we have only juicebox parameters.
        // Strip href of current parameters, if any
        let idx = href.indexOf("?");
        if (idx > 0) href = href.substring(0, idx);

        const jbUrl = await hic.shortJuiceboxURL(href);

        const embedSnippet = await getEmbeddableSnippet($appContainer, config);
        const $hic_embed_url = $('#hic-embed');
        $hic_embed_url.val(embedSnippet);
        $hic_embed_url.get(0).select();

        let shareUrl = jbUrl;

        // Shorten second time
        // e.g. converts https://aidenlab.org/juicebox?juiceboxURL=https://goo.gl/WUb1mL  to https://goo.gl/ERHp5u

        const $hic_share_url = $('#hic-share-url');
        $hic_share_url.val(shareUrl);
        $hic_share_url.get(0).select();

        const tweetContainer = $('#tweetButtonContainer');
        tweetContainer.empty();

        $('#emailButton').attr('href', 'mailto:?body=' + shareUrl);

        if (shareUrl.length < 100) {

            await window.twttr.widgets.createShareButton(shareUrl, tweetContainer.get(0), { text: 'Contact map: ' });
            console.log("Tweet button updated");

            // QR code generation
            if (qrcode) {
                qrcode.clear();
                $('hic-qr-code-image').empty();
            } else {
                qrcode = new QRCode(document.getElementById("hic-qr-code-image"), { width: 128, height: 128, correctLevel: QRCode.CorrectLevel.H });
            }

            qrcode.makeCode(shareUrl);
        }

    });

    $hic_share_url_modal.on('hidden.bs.modal', function (e) {
        $('#hic-embed-container').hide();
        $('#hic-qr-code-image').hide();
    });

    $('#hic-track-dropdown').parent().on('shown.bs.dropdown', function () {
        var browser;

        browser = hic.HICBrowser.getCurrentBrowser();
        if (undefined === browser || undefined === browser.dataset) {
            Alert.presentAlert('Contact map must be loaded and selected before loading tracks');
        }
    });

    $('#hic-embed-button').on('click', function (e) {
        $('#hic-qr-code-image').hide();
        $('#hic-embed-container').toggle();
    });

    $('#hic-qr-code-button').on('click', function (e) {
        $('#hic-embed-container').hide();
        $('#hic-qr-code-image').toggle();
    });

    const $contact_map_select_modal = $('#hic-contact-map-select-modal');
    $('#dataset_selector').on('change', function (e) {

        const url = $(this).val();
        const $selected = $(this).find('option:selected');

        const browser = hic.HICBrowser.getCurrentBrowser();
        if (undefined === browser) {
            Alert.presentAlert('ERROR: you must select a map panel by clicking the panel header.');
        } else {
            loadHicFile(url, $selected.text());
        }

        $contact_map_select_modal.modal('hide');

        $(this).find('option').removeAttr("selected");

    });

    $('#hic-load-local-file').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const file = ($(this).get(0).files)[0];

            const { name } = file;
            const suffix = name.substr(name.lastIndexOf('.') + 1);

            if ('hic' === suffix) {
                loadHicFile(file, name);
            } else {
                loadTracks([{ url: file, name }]);
            }
        }

        $(this).val("");
        $('#hic-load-local-file-modal').modal('hide');

    });

    $('#hic-load-url').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {
            const url = $(this).val();
            loadHicFile( url, 'unnamed' );
        }

        $(this).val("");
        $('#hic-load-url-modal').modal('hide');

    });

    $('#track-load-url').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {
            loadTracks([{ url: $(this).val() }]);
        }

        $(this).val("");
        $('#track-load-url-modal').modal('hide');

    });

    $('#annotation-selector').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const path = $(this).val();
            const name = $(this).find('option:selected').text();

            let config = {url: path, name };
            if (path.indexOf("hgdownload.cse.ucsc.edu") > 0) {
                config.indexed = false   //UCSC files are never indexed
            }
            loadTracks([config]);
        }

        $('#hic-annotation-select-modal').modal('hide');
        $(this).find('option').removeAttr("selected");

    });

    $('#annotation-2D-selector').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const path = $(this).val();
            const name = $(this).find('option:selected').text();

            loadTracks([{url: path, name}]);
        }

        $('#hic-annotation-2D-select-modal').modal('hide');
        $(this).find('option').removeAttr("selected");
    });

    $('.juicebox-app-clone-button').on('click', async () => {

        let browser = undefined;
        try {
            browser = hic.createBrowser(container, { initFromUrl: false, updateHref: false });
        } catch (e) {
            console.error(e);
        }

        if (browser) {
            browser.eventBus.subscribe("GenomeChange", genomeChangeListener);
            hic.HICBrowser.setCurrentBrowser(browser);
        }

    });

    $('#hic-copy-link').on('click', function (e) {
        var success;
        $('#hic-share-url')[0].select();
        success = document.execCommand('copy');
        if (success) {
            $('#hic-share-url-modal').modal('hide');
        } else {
            alert("Copy not successful");
        }
    });

    $('#hic-embed-copy-link').on('click', function (e) {
        var success;
        $('#hic-embed')[0].select();
        success = document.execCommand('copy');
        if (success) {
            $('#hic-share-url-modal').modal('hide');
        } else {
            alert("Copy not successful");
        }
    });

    const $e = $('button[id$=-map-dropdown]');
    $e.parent().on('show.bs.dropdown', function () {
        currentContactMapDropdownButtonID = $(this).children('.dropdown-toggle').attr('id');
    });

    $e.parent().on('hide.bs.dropdown', function () {
        console.log("hide contact/control map");
    });

    hic.eventBus.subscribe("BrowserSelect", function (event) {
        updateBDropdown(event.data);
    });
};

const createEncodeTable = genomeId => encodeModal.setDatasource(new EncodeDataSource(genomeId));

const loadAnnotationSelector = async ($container, url, type) => {

    $container.empty();

    let data = undefined;

    try {
        data = await igvxhr.loadString(url);
    } catch (e) {
        Alert.presentAlert(`Error loading track menu: ${ url } ${ e }`);
    }

    let lines = data ? StringUtils.splitLines(data) : [];
    if (lines.length > 0) {

        let elements = [];
        elements.push('<option value=' + '-' + '>' + '-' + '</option>');

        for (let line of lines) {
            const tokens = line.split('\t');
            if (tokens.length > 1 && ("2D" === type || igvSupports(tokens[1]))) {
                elements.push('<option value=' + tokens[1] + '>' + tokens[0] + '</option>');
            }

        }

        $container.append(elements.join(''));

    }

};

function igvSupports(path) {

    // For now we will pretend that igv does not support bedpe, we want these loaded as 2D tracks
    if (path.endsWith(".bedpe") || path.endsWith(".bedpe.gz")) {
        return false;
    }

    let config = { url: path };
    TrackUtils.inferTrackTypes(config);
    return config.type !== undefined;

}

function loadTracks(tracks) {
    // Set some juicebox specific defaults
    for(let t of tracks) {
        t.autoscale = true;
        t.displayMode = "COLLAPSED"
    }
    hic.HICBrowser.getCurrentBrowser().loadTracks(tracks);
}

function loadHicFile(url, name) {

    var synchState, browsersWithMaps, isControl, browser, query, config, uriDecode;

    browsersWithMaps = allBrowsers.filter(function (browser) {
        return browser.dataset !== undefined;
    });

    if (browsersWithMaps.length > 0) {
        synchState = browsersWithMaps[0].getSyncState();
    }

    isControl = currentContactMapDropdownButtonID === 'hic-control-map-dropdown';

    browser = hic.HICBrowser.getCurrentBrowser();

    config = {url: url, name: name, isControl: isControl};

    if (StringUtils.isString(url) && url.includes("?")) {
        query = hic.extractQuery(url);
        uriDecode = url.includes("%2C");
        hic.decodeQuery(query, config, uriDecode);
    }

    if (isControl) {
        browser
            .loadHicControlFile(config)
            .then(function (dataset) {

            });
    } else {
        browser.reset();

        browsersWithMaps = allBrowsers.filter(function (browser) {
            return browser.dataset !== undefined;
        });

        if (browsersWithMaps.length > 0) {
            config["synchState"] = browsersWithMaps[0].getSyncState();
        }

        browser
            .loadHicFile(config)
            .then(function (ignore) {
                if (!isControl) {
                    hic.syncBrowsers(allBrowsers);
                }
                $('#hic-control-map-dropdown').removeClass('disabled');
            });
    }
}

async function getEmbeddableSnippet($appContainer, config) {
    const base = (config.embedTarget || getEmbedTarget())
    const embedUrl =  await hic.shortJuiceboxURL(base);
    const height = $appContainer.height();
    return '<iframe src="' + embedUrl + '" width="100%" height="' + height + '" frameborder="0" style="border:0" allowfullscreen></iframe>';
}

/**
 * Get the default embed html target.  Assumes an "embed.html" file in same directory as this page
 */
function getEmbedTarget() {

    var href, idx;
    href = new String(window.location.href);

    idx = href.indexOf("?");
    if (idx > 0) href = href.substring(0, idx);

    idx = href.lastIndexOf("/");
    return href.substring(0, idx) + "/embed.html"

}

const populatePulldown = async menu => {

    const { id, items } = menu;

    let data = undefined;
    try {
        data = await igvxhr.loadString(items)
    } catch (e) {
        console.error(e);
    }

    if (data) {

        const lines = StringUtils.splitLines(data);

        const parent = $("#" + id);

        for (let line of lines) {

            const tokens = line.split('\t');
            if (tokens.length > 1) {
                parent.append($('<option value="' + tokens[0] + '">' + tokens[1] + '</option>'))
            }

        }

        // parent.selectpicker("refresh");

    }

};

function checkBDropdown() {
    updateBDropdown(hic.HICBrowser.getCurrentBrowser());
}

function updateBDropdown(browser) {
    if (browser) {
        if (browser.dataset) {
            $('#hic-control-map-dropdown').removeClass('disabled');
        } else {
            $('#hic-control-map-dropdown').addClass('disabled');
        }
    }
}

export { initializationHelper, loadTracks }
<commit_msg>session load/save edits<commit_after>import { Alert, TrackUtils, StringUtils, igvxhr, SessionFileLoad } from '../../../node_modules/igv-widgets/dist/igv-widgets.js';
import ModalTable from '../../../node_modules/data-modal/js/modalTable.js';
import EncodeDataSource from '../../../node_modules/data-modal/js/encodeDataSource.js';
import hic from "../../../js/api.js";
import QRCode from "./qrcode.js";
import { allBrowsers } from './site.js';
import SessionController from "../../../js/sessionController.js";
import { toJSON } from "../../../js/init.js";

let googleEnabled = false;

let lastGenomeId = undefined;
let qrcode = undefined;
let currentContactMapDropdownButtonID = undefined;
let sessionController;

let $hic_share_url_modal;

const encodeModal = new ModalTable({ id: 'hic-encode-modal', title: 'ENCODE', selectHandler: selected => loadTracks(selected) });

const initializationHelper = async ($appContainer, config) => {

    const genomeChangeListener = {

        receiveEvent: async event => {

            const { data: genomeId } = event;
            if (lastGenomeId !== genomeId) {

                lastGenomeId = genomeId;

                if (config.trackMenu) {
                    let tracksURL = config.trackMenu.items.replace("$GENOME_ID", genomeId);
                    await loadAnnotationSelector($('#' + config.trackMenu.id), tracksURL, "1D");
                }

                if (config.trackMenu2D) {
                    let annotations2dURL = config.trackMenu2D.items.replace("$GENOME_ID", genomeId);
                    await loadAnnotationSelector($('#' + config.trackMenu2D.id), annotations2dURL, "2D");
                }

                if (EncodeDataSource.supportsGenome(genomeId)) {
                    $('#hic-encode-modal-button').show();
                    createEncodeTable(genomeId);
                } else {
                    $('#hic-encode-modal-button').hide();
                }
            }
        }
    };

    for (let browser of allBrowsers) {
        browser.eventBus.subscribe("GenomeChange", genomeChangeListener);
        browser.eventBus.subscribe("MapLoad", checkBDropdown);
        updateBDropdown(browser);
    }

    // Must manually trigger the genome change event on initial load
    if (hic.HICBrowser.currentBrowser && hic.HICBrowser.currentBrowser.genome) {
        await genomeChangeListener.receiveEvent({data: hic.HICBrowser.currentBrowser.genome.id})
    }

    // session file load config
    const sessionFileLoadConfig =
        {
            localFileInput: document.querySelector('#igv-app-dropdown-local-session-file-input'),
            dropboxButton: document.querySelector('#igv-app-dropdown-dropbox-session-file-button'),
            googleEnabled,
            googleDriveButton: document.querySelector('#igv-app-dropdown-google-drive-session-file-button'),
            loadHandler: config => {
                hic.loadSession(config)
            }
        };

    // Session Controller
    const sessionControllerConfig =
        {
            sessionLoadModal: document.querySelector('#igv-app-session-from-url-modal'),
            sessionSaveModal: document.querySelector('#igv-app-session-save-modal'),
            sessionFileLoad: new SessionFileLoad(sessionFileLoadConfig),
            JSONProvider: () => toJSON()
        };
    sessionController = new SessionController(sessionControllerConfig);

    if (config.mapMenu) {
        await populatePulldown(config.mapMenu);
    }

    $hic_share_url_modal = $('#hic-share-url-modal');

    $hic_share_url_modal.on('show.bs.modal', async function (e) {

        let href = new String(window.location.href);

        // This js file is specific to the aidenlab site, and we know we have only juicebox parameters.
        // Strip href of current parameters, if any
        let idx = href.indexOf("?");
        if (idx > 0) href = href.substring(0, idx);

        const jbUrl = await hic.shortJuiceboxURL(href);

        const embedSnippet = await getEmbeddableSnippet($appContainer, config);
        const $hic_embed_url = $('#hic-embed');
        $hic_embed_url.val(embedSnippet);
        $hic_embed_url.get(0).select();

        let shareUrl = jbUrl;

        // Shorten second time
        // e.g. converts https://aidenlab.org/juicebox?juiceboxURL=https://goo.gl/WUb1mL  to https://goo.gl/ERHp5u

        const $hic_share_url = $('#hic-share-url');
        $hic_share_url.val(shareUrl);
        $hic_share_url.get(0).select();

        const tweetContainer = $('#tweetButtonContainer');
        tweetContainer.empty();

        $('#emailButton').attr('href', 'mailto:?body=' + shareUrl);

        if (shareUrl.length < 100) {

            await window.twttr.widgets.createShareButton(shareUrl, tweetContainer.get(0), { text: 'Contact map: ' });
            console.log("Tweet button updated");

            // QR code generation
            if (qrcode) {
                qrcode.clear();
                $('hic-qr-code-image').empty();
            } else {
                qrcode = new QRCode(document.getElementById("hic-qr-code-image"), { width: 128, height: 128, correctLevel: QRCode.CorrectLevel.H });
            }

            qrcode.makeCode(shareUrl);
        }

    });

    $hic_share_url_modal.on('hidden.bs.modal', function (e) {
        $('#hic-embed-container').hide();
        $('#hic-qr-code-image').hide();
    });

    $('#hic-track-dropdown').parent().on('shown.bs.dropdown', function () {
        var browser;

        browser = hic.HICBrowser.getCurrentBrowser();
        if (undefined === browser || undefined === browser.dataset) {
            Alert.presentAlert('Contact map must be loaded and selected before loading tracks');
        }
    });

    $('#hic-embed-button').on('click', function (e) {
        $('#hic-qr-code-image').hide();
        $('#hic-embed-container').toggle();
    });

    $('#hic-qr-code-button').on('click', function (e) {
        $('#hic-embed-container').hide();
        $('#hic-qr-code-image').toggle();
    });

    const $contact_map_select_modal = $('#hic-contact-map-select-modal');
    $('#dataset_selector').on('change', function (e) {

        const url = $(this).val();
        const $selected = $(this).find('option:selected');

        const browser = hic.HICBrowser.getCurrentBrowser();
        if (undefined === browser) {
            Alert.presentAlert('ERROR: you must select a map panel by clicking the panel header.');
        } else {
            loadHicFile(url, $selected.text());
        }

        $contact_map_select_modal.modal('hide');

        $(this).find('option').removeAttr("selected");

    });

    $('#hic-load-local-file').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const file = ($(this).get(0).files)[0];

            const { name } = file;
            const suffix = name.substr(name.lastIndexOf('.') + 1);

            if ('hic' === suffix) {
                loadHicFile(file, name);
            } else {
                loadTracks([{ url: file, name }]);
            }
        }

        $(this).val("");
        $('#hic-load-local-file-modal').modal('hide');

    });

    $('#hic-load-url').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {
            const url = $(this).val();
            loadHicFile( url, 'unnamed' );
        }

        $(this).val("");
        $('#hic-load-url-modal').modal('hide');

    });

    $('#track-load-url').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {
            loadTracks([{ url: $(this).val() }]);
        }

        $(this).val("");
        $('#track-load-url-modal').modal('hide');

    });

    $('#annotation-selector').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const path = $(this).val();
            const name = $(this).find('option:selected').text();

            let config = {url: path, name };
            if (path.indexOf("hgdownload.cse.ucsc.edu") > 0) {
                config.indexed = false   //UCSC files are never indexed
            }
            loadTracks([config]);
        }

        $('#hic-annotation-select-modal').modal('hide');
        $(this).find('option').removeAttr("selected");

    });

    $('#annotation-2D-selector').on('change', function (e) {

        if (undefined === hic.HICBrowser.getCurrentBrowser()) {
            Alert.presentAlert('ERROR: you must select a map panel.');
        } else {

            const path = $(this).val();
            const name = $(this).find('option:selected').text();

            loadTracks([{url: path, name}]);
        }

        $('#hic-annotation-2D-select-modal').modal('hide');
        $(this).find('option').removeAttr("selected");
    });

    $('.juicebox-app-clone-button').on('click', async () => {

        let browser = undefined;
        try {
            browser = hic.createBrowser(container, { initFromUrl: false, updateHref: false });
        } catch (e) {
            console.error(e);
        }

        if (browser) {
            browser.eventBus.subscribe("GenomeChange", genomeChangeListener);
            hic.HICBrowser.setCurrentBrowser(browser);
        }

    });

    $('#hic-copy-link').on('click', function (e) {
        var success;
        $('#hic-share-url')[0].select();
        success = document.execCommand('copy');
        if (success) {
            $('#hic-share-url-modal').modal('hide');
        } else {
            alert("Copy not successful");
        }
    });

    $('#hic-embed-copy-link').on('click', function (e) {
        var success;
        $('#hic-embed')[0].select();
        success = document.execCommand('copy');
        if (success) {
            $('#hic-share-url-modal').modal('hide');
        } else {
            alert("Copy not successful");
        }
    });

    const $e = $('button[id$=-map-dropdown]');
    $e.parent().on('show.bs.dropdown', function () {
        currentContactMapDropdownButtonID = $(this).children('.dropdown-toggle').attr('id');
    });

    $e.parent().on('hide.bs.dropdown', function () {
        console.log("hide contact/control map");
    });

    hic.eventBus.subscribe("BrowserSelect", function (event) {
        updateBDropdown(event.data);
    });
};

const createEncodeTable = genomeId => encodeModal.setDatasource(new EncodeDataSource(genomeId));

const loadAnnotationSelector = async ($container, url, type) => {

    $container.empty();

    let data = undefined;

    try {
        data = await igvxhr.loadString(url);
    } catch (e) {
        Alert.presentAlert(`Error loading track menu: ${ url } ${ e }`);
    }

    let lines = data ? StringUtils.splitLines(data) : [];
    if (lines.length > 0) {

        let elements = [];
        elements.push('<option value=' + '-' + '>' + '-' + '</option>');

        for (let line of lines) {
            const tokens = line.split('\t');
            if (tokens.length > 1 && ("2D" === type || igvSupports(tokens[1]))) {
                elements.push('<option value=' + tokens[1] + '>' + tokens[0] + '</option>');
            }

        }

        $container.append(elements.join(''));

    }

};

function igvSupports(path) {

    // For now we will pretend that igv does not support bedpe, we want these loaded as 2D tracks
    if (path.endsWith(".bedpe") || path.endsWith(".bedpe.gz")) {
        return false;
    }

    let config = { url: path };
    TrackUtils.inferTrackTypes(config);
    return config.type !== undefined;

}

function loadTracks(tracks) {
    // Set some juicebox specific defaults
    for(let t of tracks) {
        t.autoscale = true;
        t.displayMode = "COLLAPSED"
    }
    hic.HICBrowser.getCurrentBrowser().loadTracks(tracks);
}

function loadHicFile(url, name) {

    var synchState, browsersWithMaps, isControl, browser, query, config, uriDecode;

    browsersWithMaps = allBrowsers.filter(function (browser) {
        return browser.dataset !== undefined;
    });

    if (browsersWithMaps.length > 0) {
        synchState = browsersWithMaps[0].getSyncState();
    }

    isControl = currentContactMapDropdownButtonID === 'hic-control-map-dropdown';

    browser = hic.HICBrowser.getCurrentBrowser();

    config = {url: url, name: name, isControl: isControl};

    if (StringUtils.isString(url) && url.includes("?")) {
        query = hic.extractQuery(url);
        uriDecode = url.includes("%2C");
        hic.decodeQuery(query, config, uriDecode);
    }

    if (isControl) {
        browser
            .loadHicControlFile(config)
            .then(function (dataset) {

            });
    } else {
        browser.reset();

        browsersWithMaps = allBrowsers.filter(function (browser) {
            return browser.dataset !== undefined;
        });

        if (browsersWithMaps.length > 0) {
            config["synchState"] = browsersWithMaps[0].getSyncState();
        }

        browser
            .loadHicFile(config)
            .then(function (ignore) {
                if (!isControl) {
                    hic.syncBrowsers(allBrowsers);
                }
                $('#hic-control-map-dropdown').removeClass('disabled');
            });
    }
}

async function getEmbeddableSnippet($appContainer, config) {
    const base = (config.embedTarget || getEmbedTarget())
    const embedUrl =  await hic.shortJuiceboxURL(base);
    const height = $appContainer.height();
    return '<iframe src="' + embedUrl + '" width="100%" height="' + height + '" frameborder="0" style="border:0" allowfullscreen></iframe>';
}

/**
 * Get the default embed html target.  Assumes an "embed.html" file in same directory as this page
 */
function getEmbedTarget() {

    var href, idx;
    href = new String(window.location.href);

    idx = href.indexOf("?");
    if (idx > 0) href = href.substring(0, idx);

    idx = href.lastIndexOf("/");
    return href.substring(0, idx) + "/embed.html"

}

const populatePulldown = async menu => {

    const { id, items } = menu;

    let data = undefined;
    try {
        data = await igvxhr.loadString(items)
    } catch (e) {
        console.error(e);
    }

    if (data) {

        const lines = StringUtils.splitLines(data);

        const parent = $("#" + id);

        for (let line of lines) {

            const tokens = line.split('\t');
            if (tokens.length > 1) {
                parent.append($('<option value="' + tokens[0] + '">' + tokens[1] + '</option>'))
            }

        }

        // parent.selectpicker("refresh");

    }

};

function checkBDropdown() {
    updateBDropdown(hic.HICBrowser.getCurrentBrowser());
}

function updateBDropdown(browser) {
    if (browser) {
        if (browser.dataset) {
            $('#hic-control-map-dropdown').removeClass('disabled');
        } else {
            $('#hic-control-map-dropdown').addClass('disabled');
        }
    }
}

export { initializationHelper, loadTracks }
<|endoftext|>


<commit_before>if(!String.prototype.supplant) { // credit to Crockford for this supplant function
    String.prototype.supplant = function(o) {
        return this.replace(
            /\{([^{}]*)\}/g,
            function (a, b) {
                var r = o[b];
                return typeof r === 'string' || typeof r === 'number' ? r : a;
            }
        );
    };
}

if (!Function.prototype.bind) { // credit to Crockford for this bind function
    Function.prototype.bind = function(oThis) {
        if (typeof this !== "function") {
            // closest thing possible to the ECMAScript 5 internal IsCallable function
            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {},
            fBound = function () {
                return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();

        return fBound;
    };
}

var TicTacToe = function () { // current function constructor
      this.init(); // ?? ask Eftar
  };
// this is the prototype obect associated with the above function constructor
TicTacToe.prototype = { // give all instances of TicTacToe class the following methods and values
    // every object linked to the prototype object which they inherit properties from
    // the prototype object is where inherited methods and values are deposited
    boardElem: null, // empty elements by setting them to null
    resetElem: null,
    resultElem: null,
    statusElem: null,
    xTurn: true,
    gameOver: false,
    moves: 0,
    boardArr: [],

    init: function () { // first function associated with the prototype
        // bind UI
        this.resetElem = document.getElementById("reset-button");
        this.boardElem = document.getElementById("game-board");
        this.resultElem = document.getElementById("results");
        this.statusElem = document.getElementById("status");
        this.reset();
        // current binded events on clicking reset and gameboard
        this.resetElem.onclick = function () {
            this.reset();
        }.bind(this); // this now bounded to the this parameter of the outer function
        // (bind() instead of writing var that = this)
        this.boardElem.onclick = function (e) { // current click event handler (e is the event object passed as an arg)
            e = e || event; // event sometimes available through the global variable event (for IE)
            var source = e.boardElem || e.target; // event target is the object which
            // the event is associated
            this.updateModel({ // parse JSON containing position of button clicked & current value
                position: source.getAttribute("data-position"), // events bubble up the DOM Tree
                currentValue: source.value || null // the existing value X or O in our case
            })
        }.bind(this); // this now bounded to the this parameter of the outer function
    },

    reset: function () {
        // each time game is reseted, re-start values
        for (var i = 0; i <= 8; i += 1) { // null all squares 1 - 9
            this.boardArr[i] = null;
        }
        this.moves = 0;
        this.gameOver = false;
        this.xTurn = true; // player that moves first will be X
    },

    // Updates the model
    updateModel: function(obj) {
        if  (this.boardArr[obj.position] === null && this.gameOver !== true) { // check if each square is empy
        // & game over
            this.moves += 1;
            this.boardArr[obj.position] = this.xTurn ? "X" : "O"; // ternary operator: test (boolean) and
            // exp 1 if truthy & exp2 if falsy
            this.xTurn = !this.xTurn; // enable taking turns between X and O
            this.statusElem.innerHTML = "It is the turn of " + (this.xTurn ? "X" : "O");
        }
        if  (this.boardArr === " ")
            this.checkForWinner(); // update checkForWinner method using the board array
    },

    checkForWinner: function () { // check all 8 winning combinations in boardArr
        // check if there are three Xs or three Os in a row
        var winningCombos = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
                            [0, 3, 6], [1, 4, 7], [2, 5, 8],
                            [0, 4, 8], [2, 4, 6]
        ];
        if (arr[1] === arr[2] && arr[2] === arr[3] && arr[1] !== "") {
            this.resultElem.innerHTML = arr[1] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        } /*else if (arr[4] === arr[5] && arr[5] === arr[6] && arr[4] !== "") {
            this.resultElem.innerHTML = arr[4] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        } else if (arr[7] === arr[8] && arr[8] == arr[9] && arr[7] !== "") {
            this.resultElem.innerHTML = arr[7] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        }
        // check if there are three Xs or three Os in a column
        else if (arr[1] === arr[4] && arr[4] === arr[7] && arr[1] !== "") {
            this.resultElem.innerHTML = arr[1] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        } else if (arr[2] === arr[5] && arr[5] === arr[8] && arr[2] !== "") {
            this.resultElem.innerHTML = arr[2] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        } else if (arr[3] === arr[6] && arr[6] == arr[9] && arr[3] !== "") {
            this.resultElem.innerHTML = arr[3] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        }
        // check if there are three Xs or three Os in a diagonal
        else if (arr[7] === arr[5] && arr[5] === arr[3] && arr[7] !== "") {
            this.resultElem.innerHTML = arr[7] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        } else if (arr[1] === arr[5] && arr[5] === arr[9] && arr[1] !== "") {
            this.resultElem.innerHTML = arr[1] + ' wins';
            this.gameOver = true;
            this.statusElem.innerHTML = " ";
            return;
        }
        else if (this.moves === 9){
            this.resultElem.innerHTML = "draw";
            this.gameOver = true;
            return;
        } */
        else {
            this.resultElem.innerHTML = " ";
            return;
        }
    }
};

var playGame = new TicTacToe(); // new object which inherits from TicTacToe<commit_msg>third refactor<commit_after>if(!String.prototype.supplant) { // credit to Crockford for this supplant function
    String.prototype.supplant = function(o) {
        return this.replace(
            /\{([^{}]*)\}/g,
            function (a, b) {
                var r = o[b];
                return typeof r === 'string' || typeof r === 'number' ? r : a;
            }
        );
    };
}

if (!Function.prototype.bind) { // credit to Crockford for this bind function
    Function.prototype.bind = function(oThis) {
        if (typeof this !== "function") {
            // closest thing possible to the ECMAScript 5 internal IsCallable function
            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {},
            fBound = function () {
                return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();

        return fBound;
    };
}

var TicTacToe = function () { // current function constructor
      this.init(); // ?? ask Eftar
  };
// this is the prototype obect associated with the above function constructor
TicTacToe.prototype = { // give all instances of TicTacToe class the following methods and values
    // every object linked to the prototype object which they inherit properties from
    // the prototype object is where inherited methods and values are deposited
    boardElem: null, // empty elements by setting them to null
    resetElem: null,
    resultElem: null,
    statusElem: null,
    xTurn: true,
    gameOver: false,
    moves: 0,
    boardArr: [],

    init: function () { // first function associated with the prototype
        // bind UI
        this.resetElem = document.getElementById("reset-button");
        this.boardElem = document.getElementById("game-board");
        this.resultElem = document.getElementById("results");
        this.statusElem = document.getElementById("status");
        this.reset();
        // current binded events on clicking reset and gameboard
        this.resetElem.onclick = function () {
            this.reset();
        }.bind(this); // this now bounded to the this parameter of the outer function
        // (bind() instead of writing var that = this)
        this.boardElem.onclick = function (e) { // current click event handler (e is the event object passed as an arg)
            e = e || event; // event sometimes available through the global variable event (for IE)
            var source = e.boardElem || e.target; // event target is the object which
            // the event is associated
            this.updateModel({ // parse JSON containing position of button clicked & current value
                position: source.getAttribute("data-position"), // events bubble up the DOM Tree
                currentValue: source.value || null // the existing value X or O in our case
            })
        }.bind(this); // this now bounded to the this parameter of the outer function
    },

    reset: function () {
        // each time game is reseted, re-start values
        for (var i = 0; i <= 8; i += 1) { // null all squares 1 - 9
            this.boardArr[i] = null;
        }
        this.moves = 0;
        this.gameOver = false;
        this.xTurn = true; // player that moves first will be X
    },

    // Updates the model
    updateModel: function(obj) {
        if  (this.boardArr[obj.position] === null && this.gameOver !== true) { // check if each square is empy
        // & game over
            this.moves += 1;
            this.boardArr[obj.position] = this.xTurn ? "X" : "O"; // ternary operator: test (boolean) and
            // exp 1 if truthy & exp2 if falsy
            this.xTurn = !this.xTurn; // enable taking turns between X and O
            this.statusElem.innerHTML = "It is the turn of " + (this.xTurn ? "X" : "O");
        } // need to stop updating model once all squares have been filled
        this.checkForWinningMove();
    },

    checkForWinningMove: function () { // check all 8 winning combinations in boardArr
        var winningCombo = [[0, 1, 2], [3, 4, 5], [6, 7, 8],   // all winning combos nested arrays
                            [0, 3, 6], [1, 4, 7], [2, 5, 8],
                            [0, 4, 8], [2, 4, 6]
        ];
        // check if there is three Xs or Os in a row
        if (this.boardArr[0] === this.boardArr[1] && this.boardArr[1] === this.boardArr[2] && this.boardArr[0] !== null) {
            return true;
            alert(this.boardArr[0] + " wins");
        } else if (this.boardArr[3] === this.boardArr[4] && this.boardArr[4] === this.boardArr[5] && this.boardArr[3] !== null) {
            return true;
            alert(this.boardArr[3] + " wins");
        } else if (this.boardArr[6] === this.boardArr[7] && this.boardArr[7] === this.boardArr[8] && this.boardArr[6] !== null) {
           return true;
           alert(this.boardArr[6] + " wins");
        // check if there is three Xs or Os in a column
        } else if (this.boardArr[0] === this.boardArr[3] && this.boardArr[3] === this.boardArr[6] && this.boardArr[0] !== null) {
            return true;
            alert(this.boardArr[0] + " wins");
        } else if (this.boardArr[1] === this.boardArr[4] && this.boardArr[4] === this.boardArr[7] && this.boardArr[1] !== null) {
            return true;
            alert(this.boardArr[1] + " wins");
        } else if (this.boardArr[2] === this.boardArr[5] && this.boardArr[5] === this.boardArr[8] && this.boardArr[2] !== null) {
            return true;
            alert(this.boardArr[2] + " wins");
        // check if there is three Xs or Os in a diagonal
        } else if (this.boardArr[0] === this.boardArr[4] && this.boardArr[4] === this.boardArr[8] && this.boardArr[0] !== null) {
            return true;
            alert(this.boardArr[0] + " wins");
        } else if (this.boardArr[2] === this.boardArr[4] && this.boardArr[4] === this.boardArr[6] && this.boardArr[2] !== null) {
            return true;
            alert(this.boardArr[2] + " wins");
        }
        return false;
        alert("draw");
    }
};

var playGame = new TicTacToe(); // new object which inherits from TicTacToe<|endoftext|>


<commit_before>

/**
 * a HUD container and child items
 */

game.HUD = game.HUD || {};

game.HUD.Container = me.Container.extend({

    init: function() {
        // call the constructor
        this._super(me.Container, "init");

        // persistent across level change
        this.isPersistent = true;

        // Use screen coordinates
        this.floating = true;

        // make sure our object is always draw first
        this.z = Infinity;

        // give a name
        this.name = "HUD";

        // add our child score object at position
        this.addChild(new game.HUD.ScoreItem(-10, -40));

        // add our fullscreen control object
        this.addChild(new game.HUD.FSControl(10, 10));

        // add our audio control object
        this.addChild(new game.HUD.AudioControl(10 + 48 + 10, 10));
    }
});

/**
 * a basic control to toggle fullscreen on/off
 */
game.HUD.FSControl = me.GUI_Object.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this._super(me.GUI_Object, "init", [ x, y, {
            texture: game.texture,
            region : "shadedDark30.png"
        } ]);
        this.setOpacity(0.5);
        this.anchorPoint.set(0, 0);
    },

    /**
     * function called when the pointer is over the object
     */
    onOver : function (/* event */) {
        this.setOpacity(1.0);
    },

    /**
     * function called when the pointer is leaving the object area
     */
    onOut : function (/* event */) {
        this.setOpacity(0.5);
    },

    /**
     * function called when the object is clicked on
     */
    onClick : function (/* event */) {
        if (!me.device.isFullscreen) {
            me.device.requestFullscreen();
        } else {
            me.device.exitFullscreen();
        }
        return false;
    }
});

/**
 * a basic control to toggle fullscreen on/off
 */
game.HUD.AudioControl = me.GUI_Object.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this._super(me.GUI_Object, "init", [ x, y, {
            texture: game.texture,
            region : "shadedDark13.png" // ON by default
        } ]);

        // offset of the two used images
        this.offset_on = game.texture.getRegion("shadedDark13.png").offset;
        this.offset_off = game.texture.getRegion("shadedDark15.png").offset;

        this.anchorPoint.set(0, 0);
        this.setOpacity(0.5);

        this.isMute = false;
    },

    /**
     * function called when the pointer is over the object
     */
    onOver : function (/* event */) {
        this.setOpacity(1.0);
    },

    /**
     * function called when the pointer is leaving the object area
     */
    onOut : function (/* event */) {
        this.setOpacity(0.5);
    },

    /**
     * function called when the object is clicked on
     */
    onClick : function (/* event */) {
        if (this.isMute) {
            me.audio.unmuteAll();
            this.offset.setV(this.offset_on);
            this.isMute = false;
        } else {
            me.audio.muteAll();
            this.offset.setV(this.offset_off);
            this.isMute = true;
        }
        return false;
    }
});

/**
 * a basic HUD item to display score
 */
game.HUD.ScoreItem = me.Renderable.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this.relative = new me.Vector2d(x, y);

        // call the super constructor
        // (size does not matter here)
        this._super(me.Renderable, "init", [
            me.game.viewport.width + x,
            me.game.viewport.height + y,
            10,
            10
        ]);

        // create a font
        this.font = new me.BitmapFont("atascii", {x:24});
        this.font.alignText = "bottom";
        this.font.set("right", 1.6);

        // local copy of the global score
        this.score = -1;
    },

    /**
     * update function
     */
    update : function (/*dt*/) {
        this.pos.x = me.game.viewport.width + this.relative.x;
        this.pos.y = me.game.viewport.height + this.relative.y;

        // we don't draw anything fancy here, so just
        // return true if the score has been updated
        if (this.score !== game.data.score) {
            this.score = game.data.score;
            return true;
        }
        return false;
    },

    /**
     * draw the score
     */
    draw : function (renderer) {
        this.font.draw (renderer, game.data.score, this.pos.x, this.pos.y);
    }

});
<commit_msg>[#747] do not add the fullscreen control on mobile devices<commit_after>

/**
 * a HUD container and child items
 */

game.HUD = game.HUD || {};

game.HUD.Container = me.Container.extend({

    init: function() {
        // call the constructor
        this._super(me.Container, "init");

        // persistent across level change
        this.isPersistent = true;

        // Use screen coordinates
        this.floating = true;

        // make sure our object is always draw first
        this.z = Infinity;

        // give a name
        this.name = "HUD";

        // add our child score object at position
        this.addChild(new game.HUD.ScoreItem(-10, -40));

        // add our audio control object
        this.addChild(new game.HUD.AudioControl(10, 10));

        if (!me.device.isMobile) {
            // add our fullscreen control object
            this.addChild(new game.HUD.FSControl(10 + 48 + 10, 10));
        }
    }
});

/**
 * a basic control to toggle fullscreen on/off
 */
game.HUD.FSControl = me.GUI_Object.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this._super(me.GUI_Object, "init", [ x, y, {
            texture: game.texture,
            region : "shadedDark30.png"
        } ]);
        this.setOpacity(0.5);
        this.anchorPoint.set(0, 0);
    },

    /**
     * function called when the pointer is over the object
     */
    onOver : function (/* event */) {
        this.setOpacity(1.0);
    },

    /**
     * function called when the pointer is leaving the object area
     */
    onOut : function (/* event */) {
        this.setOpacity(0.5);
    },

    /**
     * function called when the object is clicked on
     */
    onClick : function (/* event */) {
        if (!me.device.isFullscreen) {
            me.device.requestFullscreen();
        } else {
            me.device.exitFullscreen();
        }
        return false;
    }
});

/**
 * a basic control to toggle fullscreen on/off
 */
game.HUD.AudioControl = me.GUI_Object.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this._super(me.GUI_Object, "init", [ x, y, {
            texture: game.texture,
            region : "shadedDark13.png" // ON by default
        } ]);

        // offset of the two used images
        this.offset_on = game.texture.getRegion("shadedDark13.png").offset;
        this.offset_off = game.texture.getRegion("shadedDark15.png").offset;

        this.anchorPoint.set(0, 0);
        this.setOpacity(0.5);

        this.isMute = false;
    },

    /**
     * function called when the pointer is over the object
     */
    onOver : function (/* event */) {
        this.setOpacity(1.0);
    },

    /**
     * function called when the pointer is leaving the object area
     */
    onOut : function (/* event */) {
        this.setOpacity(0.5);
    },

    /**
     * function called when the object is clicked on
     */
    onClick : function (/* event */) {
        if (this.isMute) {
            me.audio.unmuteAll();
            this.offset.setV(this.offset_on);
            this.isMute = false;
        } else {
            me.audio.muteAll();
            this.offset.setV(this.offset_off);
            this.isMute = true;
        }
        return false;
    }
});

/**
 * a basic HUD item to display score
 */
game.HUD.ScoreItem = me.Renderable.extend({
    /**
     * constructor
     */
    init: function(x, y) {
        this.relative = new me.Vector2d(x, y);

        // call the super constructor
        // (size does not matter here)
        this._super(me.Renderable, "init", [
            me.game.viewport.width + x,
            me.game.viewport.height + y,
            10,
            10
        ]);

        // create a font
        this.font = new me.BitmapFont("atascii", {x:24});
        this.font.alignText = "bottom";
        this.font.set("right", 1.6);

        // local copy of the global score
        this.score = -1;
    },

    /**
     * update function
     */
    update : function (/*dt*/) {
        this.pos.x = me.game.viewport.width + this.relative.x;
        this.pos.y = me.game.viewport.height + this.relative.y;

        // we don't draw anything fancy here, so just
        // return true if the score has been updated
        if (this.score !== game.data.score) {
            this.score = game.data.score;
            return true;
        }
        return false;
    },

    /**
     * draw the score
     */
    draw : function (renderer) {
        this.font.draw (renderer, game.data.score, this.pos.x, this.pos.y);
    }

});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014 by Center Open Middleware. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
'use strict';

var API = (function() {
    var _self;

    _self = {
        SW : {
            Contacts : require('API.Contacts'),
            Calendar : '',
            FileSystem : '',
            DataBase : '',
            Log : '',
            Map : '',
            Notification : '',
            Social : ''
        },
        HW : {
            Acceloremeter : require('API.Accelerometer'),
            Battery : require('API.Battery'),
            Camera : '',
            GeoLocation : '',
            Gesture : '',
            Media : '',
            Network : '',
            System : require('API.System')
        }
    };

    _self.events = {
        activeHandlers: {},
        availableEvents: {}
    };

    var _initEvents = function _initEvents() {
        var key, eventId, publicName, eventData;
        /* TODO new class eventData
         * API.Example.events = {
         *      'publicEventName': {
         *          event: 'titaniumeventname',
         *          listener: Ti.thePathToMethod.addEventListener
         *      }
         * };
         */
        for (key in _self.SW) {
            if (_self.SW[key].events) {
                for (eventId in _self.SW[key].events) {
                    publicName = enventId;
                    eventData = _self.SW[key].events[eventId];
                    _self.events.availableEvents[publicName] = eventData;
                }
            }
        }
        for (key in _self.HW) {
            if (_self.HW[key].events) {
                for (eventId in _self.HW[key].events) {
                    publicName = enventId;
                    eventData = _self.HW[key].events[eventId];
                    _self.events.availableEvents[publicName] = eventData;
                }
            }
        }
    };

    /** Transport to html a internal event
     * @param: {eventName} the name of the Titanium event.
     * @param: {data} event data.
     * @return : Bool true if success or false if error*/
    var _fireHTMLEvents = function _fireHTMLEvents(eventName, data) {
        var key, viewId;
        if (_self.events.activeHandlers[eventName]) {
            for (key in _self.events.activeHandlers[eventName].views) {
                viewId = _self.events.activeHandlers[eventName].views[key];
                // This event will be received by all listeners API.Commons
                Ti.App.fireEvent(eventName, data);
            }
            return true;
        } else {
            return false;
        }
    };

    /** AddEventListener from a HTML view (througth APICommons.js TODO)
     * @param: {publicEvent} the public html name for the event.
     * @param: {viewId} the id of the interested html view.
     * @return : Bool true if success or false if error*/
    _self.events.addEventListener = function addEventListener(publicEvent, viewId) {
        var eventData, eventHandler;

        eventData = _self.events.availableEvents[publicEvent];
        if (!eventData) {
            // Public event doesn't exist
            return false;
        }
        if (_self.events.activeHandlers[publicEvent]) {
            // Main listener active yet
            _self.events.activeHandlers[publicEvent].nlisteners += 1;
            if (!_self.events.activeHandlers[publicEvent].views[viewId]) {
                _self.events.activeHandlers[publicEvent].views[viewId] = 0;
            }
            _self.events.activeHandlers[publicEvent].views[viewId] += 1 ;
        } else {
            // Create new handler
            eventHandler = function(theEvent, e) {
                _fireHTMLEvents.call(_self, theEvent, {
                        'level': e.level,
                        'state': e.state,
                        'type': e.type
                    }
                );
            }.bind(_self, publicEvent);

            // Inicialize handler for this event
            _self.events.availableEvents[publicEvent].listener.addEventListener(_self.events.availableEvents[publicEvent].event, eventHandler);
            _self.events.activeHandlers[publicEvent].handler = eventHandler;
            _self.events.activeHandlers[publicEvent].nlisteners = 1;
            _self.events.activeHandlers[publicEvent].views = {};
            _self.events.activeHandlers[publicEvent].views[viewId] = 1;
        }
    };

    /** RemoveEventListener from a HTML view (througth APICommons.js TODO)
     * @param: {publicEvent} the public html name for the event.
     * @param: {viewId} the id of the interested html view.
     * @return : Bool true if success or false if error*/
    _self.events.RemoveEventListener = function RemoveEventListener(publicEvent, viewId) {
        var eventData, eventHandler;

        eventData = _self.events.availableEvents[publicEvent];
        if (!eventData || !_self.events.activeHandlers[publicEvent]) {
            // Public event doesn't exist
            return false;
        }

        _self.events.activeHandlers[publicEvent].nlisteners -= 1;
        _self.events.activeHandlers[publicEvent].views[viewId] -= 1 ;
        _self.events.availableEvents[publicEvent].listener.removeEventListener(_self.events.availableEvents[publicEvent].event, _self.events.activeHandlers[publicEvent].handler);
    };

    /** Handler for the events from a HTML view througth APICommons.js
     * @param: {data} data = {
     *     'action': 'addEventListener'/'removeEventListener',
     *     'viewId': viewId
     * }
     **/
    _self.events.APIEventHandler = function APIEventHandler(data) {
        var dataParsed;

        dataParsed = JSON.parse(data);

        if (dataParsed.action == 'addEventListener') {
            _self.events.addEventListener(dataParsed.event, dataParsed.viewId);
        } else if (dataParsed.action == 'removeEventListener') {
            _self.events.removeEventListener(dataParsed.event, dataParsed.viewId);
        }
    };

    /** Handler for the API methods invocations from a HTML view througth APICommons.js
     * @param: {data} data = {
     *     'method': 'API.Example.getBlabla',
     *     'params': [param],
     *     'eventName': eventName
     * }
     **/
    _self.events.APIMethodHandler = function APIMethodHandler(data) {
        var result, dataParsed;

        dataParsed = JSON.parse(data);

        if (dataParsed.method && !dataParsed.params) {
            result = dataParsed.method();
        } else if (dataParsed.method && dataParsed.params) {
            result = dataParsed.method(dataParsed.params);
        } else {
            // Error. Method doesn't exist
            result = "Error. Unknown API method";
        }
        Ti.App.fireEvent(dataParsed.eventName, result);
    };

    _self.init = function init() {
        _initEvents(_self);
        Ti.App.addEventListener('APIEvent', _self.events.APIEventHandler);
        Ti.App.addEventListener('APIMethod', _self.events.APIMethodHandler);
    };

    _self.Init();
    return _self;

}());

module.exports = API;<commit_msg>[API] Improve format<commit_after>/**
 * Copyright (c) 2014 by Center Open Middleware. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
'use strict';

var API = (function() {
    var _self;

    _self = {
        SW : {
            Contacts : require('API.Contacts'),
            Calendar : '',
            FileSystem : '',
            DataBase : '',
            Log : '',
            Map : '',
            Notification : '',
            Social : ''
        },
        HW : {
            Acceloremeter : require('API.Accelerometer'),
            Battery : require('API.Battery'),
            Camera : '',
            GeoLocation : '',
            Gesture : '',
            Media : '',
            Network : '',
            System : require('API.System')
        }
    };

    _self.events = {
        activeHandlers: {},
        availableEvents: {}
    };

    var _initEvents = function _initEvents() {
        var key, eventId, publicName, eventData, enventId;

        /* TODO new class eventData
         * API.Example.events = {
         *      'publicEventName': {
         *          event: 'titaniumeventname',
         *          listener: Ti.thePathToMethod.addEventListener
         *      }
         * };
         */

        for (key in _self.SW) {
            if (_self.SW[key].events) {
                for (eventId in _self.SW[key].events) {
                    publicName = enventId;
                    eventData = _self.SW[key].events[eventId];
                    _self.events.availableEvents[publicName] = eventData;
                }
            }
        }
        for (key in _self.HW) {
            if (_self.HW[key].events) {
                for (eventId in _self.HW[key].events) {
                    publicName = enventId;
                    eventData = _self.HW[key].events[eventId];
                    _self.events.availableEvents[publicName] = eventData;
                }
            }
        }
    };

    /** Transport to html a internal event
     * @param: {eventName} the name of the Titanium event.
     * @param: {data} event data.
     * @return : Bool true if success or false if error*/
    var _fireHTMLEvents = function _fireHTMLEvents(eventName, data) {
        var key, viewId, result;

        if (_self.events.activeHandlers[eventName]) {
            for (key in _self.events.activeHandlers[eventName].views) {
                viewId = _self.events.activeHandlers[eventName].views[key];
                // This event will be received by all listeners API.Commons
                Ti.App.fireEvent(eventName, data);
            }
            result = true;
        } else {
            result = false;
        }
        return result;
    };

    /** AddEventListener from a HTML view (througth APICommons.js TODO)
     * @param: {publicEvent} the public html name for the event.
     * @param: {viewId} the id of the interested html view.
     * @return : Bool true if success or false if error*/
    _self.events.addEventListener = function addEventListener(publicEvent, viewId) {
        var eventData, eventHandler;

        eventData = _self.events.availableEvents[publicEvent];
        if (!eventData) {
            // Public event doesn't exist
            return false;
        }
        if (_self.events.activeHandlers[publicEvent]) {
            // Main listener active yet
            _self.events.activeHandlers[publicEvent].nlisteners += 1;
            if (!_self.events.activeHandlers[publicEvent].views[viewId]) {
                _self.events.activeHandlers[publicEvent].views[viewId] = 0;
            }
            _self.events.activeHandlers[publicEvent].views[viewId] += 1 ;
        } else {
            // Create new handler
            eventHandler = function(theEvent, e) {
                _fireHTMLEvents.call(_self, theEvent, {
                        'level': e.level,
                        'state': e.state,
                        'type': e.type
                    }
                );
            }.bind(_self, publicEvent);

            // Inicialize handler for this event
            _self.events.availableEvents[publicEvent].listener.addEventListener(_self.events.availableEvents[publicEvent].event, eventHandler);
            _self.events.activeHandlers[publicEvent].handler = eventHandler;
            _self.events.activeHandlers[publicEvent].nlisteners = 1;
            _self.events.activeHandlers[publicEvent].views = {};
            _self.events.activeHandlers[publicEvent].views[viewId] = 1;
        }
    };

    /** RemoveEventListener from a HTML view (througth APICommons.js TODO)
     * @param: {publicEvent} the public html name for the event.
     * @param: {viewId} the id of the interested html view.
     * @return : Bool true if success or false if error*/
    _self.events.RemoveEventListener = function RemoveEventListener(publicEvent, viewId) {
        var eventData, eventHandler;

        eventData = _self.events.availableEvents[publicEvent];
        if (!eventData || !_self.events.activeHandlers[publicEvent]) {
            // Public event doesn't exist
            return false;
        }

        _self.events.activeHandlers[publicEvent].nlisteners -= 1;
        _self.events.activeHandlers[publicEvent].views[viewId] -= 1 ;
        _self.events.availableEvents[publicEvent].listener.removeEventListener(_self.events.availableEvents[publicEvent].event, _self.events.activeHandlers[publicEvent].handler);
    };

    /** Handler for the events from a HTML view througth APICommons.js
     * @param: {data} data = {
     *     'action': 'addEventListener'/'removeEventListener',
     *     'viewId': viewId
     * }
     **/
    _self.events.APIEventHandler = function APIEventHandler(data) {
        var dataParsed;

        dataParsed = JSON.parse(data);

        if (dataParsed.action === 'addEventListener') {
            _self.events.addEventListener(dataParsed.event, dataParsed.viewId);
        } else if (dataParsed.action === 'removeEventListener') {
            _self.events.removeEventListener(dataParsed.event, dataParsed.viewId);
        }
    };

    /** Handler for the API methods invocations from a HTML view througth APICommons.js
     * @param: {data} data = {
     *     'method': 'API.Example.getBlabla',
     *     'params': [param],
     *     'eventName': eventName
     * }
     **/
    _self.events.APIMethodHandler = function APIMethodHandler(data) {
        var result, dataParsed;

        dataParsed = JSON.parse(data);

        if (dataParsed.method && !dataParsed.params) {
            result = dataParsed.method();
        } else if (dataParsed.method && dataParsed.params) {
            result = dataParsed.method(dataParsed.params);
        } else {
            // Error. Method doesn't exist
            result = "Error. Unknown API method";
        }
        Ti.App.fireEvent(dataParsed.eventName, result);
    };

    _self.init = function init() {
        _initEvents(_self);
        Ti.App.addEventListener('APIEvent', _self.events.APIEventHandler);
        Ti.App.addEventListener('APIMethod', _self.events.APIMethodHandler);
    };

    _self.Init();
    return _self;

}());

module.exports = API;<|endoftext|>


<commit_before>var ko = require('knockout');
var pikaday = require('pikaday');
require('pikaday-css');
var bootbox = require('bootbox');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var language = require('js/osfLanguage').registrations;

var template = require('raw!templates/registration-modal.html');
$(document).ready(function() {
    $('body').append(template);
});

// TODO(hrybacki): Import min/max dates from website.settings
var TWO_DAYS_FROM_TODAY_TIMESTAMP = new Date().getTime() + (2 * 24 * 60 * 60 * 1000);
var FOUR_YEARS_FROM_TODAY_TIMESTAMP = new Date().getTime() + (1460 * 24 * 60 * 60 * 1000);

var MAKE_PUBLIC = {
    value: 'immediate',
    message: 'Make registration public immediately'
};
var MAKE_EMBARGO = {
    value: 'embargo',
    message: 'Enter registration into embargo'
};
var today = new Date();

var RegistrationViewModel = function(confirm, prompts, validator) {

    var self = this;

    self.registrationOptions = [
        MAKE_PUBLIC,
        MAKE_EMBARGO
    ];
    self.registrationChoice = ko.observable(MAKE_PUBLIC.value);

    self.pikaday = ko.observable(today);
    var picker = new pikaday(
        {
            bound: true,
            field: document.getElementById('endDatePicker'),
            onSelect: function() {
                self.pikaday(picker.toString());
                self.isEmbargoEndDateValid();
            }
        }
    );
    self.embargoEndDate = ko.computed(function() {
        return new Date(self.pikaday());
    });

    var validation = [{
        validator: function() {
            var endEmbargoDateTimestamp = self.embargoEndDate().getTime() + (self.embargoEndDate().getTimezoneOffset() * 60000);
            return endEmbargoDateTimestamp > TWO_DAYS_FROM_TODAY_TIMESTAMP;
        },
        message: 'Embargo end date must be at least three days in the future.'
    }, {
	validator: function() {
            var endEmbargoDateTimestamp = self.embargoEndDate().getTime();
	        return endEmbargoDateTimestamp < FOUR_YEARS_FROM_TODAY_TIMESTAMP;
	},
	message: 'Embargo end date must be less than four years in the future.'
    }];
    if(validator) {
        validation.unshift(validator);
    }
    self.pikaday.extend({
        validation: validation
    });

    self.showEmbargoDatePicker = ko.observable(false);
    self.requestingEmbargo = ko.computed(function() {
        var choice = self.registrationChoice();
        return choice === MAKE_EMBARGO.value;
    });
    self.requestingEmbargo.subscribe(function(requestingEmbargo) {
        self.showEmbargoDatePicker(requestingEmbargo);
    });

    self.canRegister = ko.pureComputed(function() {
        if (self.requestingEmbargo()) {
            return self.pikaday.isValid();
        }
        return true;
    });

    self.confirm = confirm;
    self.preRegisterPrompts = prompts;
    self.close = bootbox.hideAll;
};
RegistrationViewModel.prototype.show = function() {
    var self = this;
    bootbox.dialog({
        size: 'large',
        title: language.registerConfirm,
        message: function() {
            ko.renderTemplate('registrationChoiceModal', self, {}, this);
        }
    });
};
RegistrationViewModel.prototype.register = function() {
    this.confirm({
        registrationChoice: this.registrationChoice(),
        embargoEndDate: this.embargoEndDate()
    });
};

module.exports = {
    ViewModel: RegistrationViewModel
};<commit_msg>Fix bug in Registration Embargo where end date 3 days away was invalid after 8pm.<commit_after>var ko = require('knockout');
var pikaday = require('pikaday');
require('pikaday-css');
var bootbox = require('bootbox');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var language = require('js/osfLanguage').registrations;

var template = require('raw!templates/registration-modal.html');
$(document).ready(function() {
    $('body').append(template);
});

// TODO(hrybacki): Import min/max dates from website.settings
var TWO_DAYS_FROM_TODAY_TIMESTAMP = new Date().getTime() + (2 * 24 * 60 * 60 * 1000);
var FOUR_YEARS_FROM_TODAY_TIMESTAMP = new Date().getTime() + (1460 * 24 * 60 * 60 * 1000);

var MAKE_PUBLIC = {
    value: 'immediate',
    message: 'Make registration public immediately'
};
var MAKE_EMBARGO = {
    value: 'embargo',
    message: 'Enter registration into embargo'
};
var today = new Date();

var RegistrationViewModel = function(confirm, prompts, validator) {

    var self = this;

    self.registrationOptions = [
        MAKE_PUBLIC,
        MAKE_EMBARGO
    ];
    self.registrationChoice = ko.observable(MAKE_PUBLIC.value);

    self.pikaday = ko.observable(today);
    var picker = new pikaday(
        {
            bound: true,
            field: document.getElementById('endDatePicker'),
            onSelect: function() {
                self.pikaday(picker.toString());
                self.isEmbargoEndDateValid();
            }
        }
    );
    self.embargoEndDate = ko.computed(function() {
        return new Date(self.pikaday());
    });

    var validation = [{
        validator: function() {
            var timeZoneOffset = self.embargoEndDate().getTimezoneOffset() * (60 * 1000);
            var endEmbargoDateTimestamp = self.embargoEndDate().getTime() + timeZoneOffset;
            return endEmbargoDateTimestamp > TWO_DAYS_FROM_TODAY_TIMESTAMP;
        },
        message: 'Embargo end date must be at least three days in the future.'
    }, {
	validator: function() {
            var endEmbargoDateTimestamp = self.embargoEndDate().getTime();
	        return endEmbargoDateTimestamp < FOUR_YEARS_FROM_TODAY_TIMESTAMP;
	},
	message: 'Embargo end date must be less than four years in the future.'
    }];
    if(validator) {
        validation.unshift(validator);
    }
    self.pikaday.extend({
        validation: validation
    });

    self.showEmbargoDatePicker = ko.observable(false);
    self.requestingEmbargo = ko.computed(function() {
        var choice = self.registrationChoice();
        return choice === MAKE_EMBARGO.value;
    });
    self.requestingEmbargo.subscribe(function(requestingEmbargo) {
        self.showEmbargoDatePicker(requestingEmbargo);
    });

    self.canRegister = ko.pureComputed(function() {
        if (self.requestingEmbargo()) {
            return self.pikaday.isValid();
        }
        return true;
    });

    self.confirm = confirm;
    self.preRegisterPrompts = prompts;
    self.close = bootbox.hideAll;
};
RegistrationViewModel.prototype.show = function() {
    var self = this;
    bootbox.dialog({
        size: 'large',
        title: language.registerConfirm,
        message: function() {
            ko.renderTemplate('registrationChoiceModal', self, {}, this);
        }
    });
};
RegistrationViewModel.prototype.register = function() {
    this.confirm({
        registrationChoice: this.registrationChoice(),
        embargoEndDate: this.embargoEndDate()
    });
};

module.exports = {
    ViewModel: RegistrationViewModel
};<|endoftext|>


<commit_before>var express = require("express")
var server = require("http").createServer();
var wss = new require("ws").Server({server});
var app = express();
var models = require("./models")
var bodyParser = require("body-parser")
var url_module = require("url")
var tokenAuth = require("./utils/tokenAuth")
var multer = require("multer")()
var models = require("./models")
var msgpack = require("msgpack5")()
var yaml = require("yamljs")

console.log("###################")
console.log("### Kyoppie API ###")
console.log("###################")
console.log("Repository: https://github.com/kyoppie/kyoppie-api")

app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(function(req,res,next){
    res.append("Access-Control-Allow-Origin","*")
    res.append("Access-Control-Allow-Method","GET, POST, OPTIONS");
    res.append("Access-Control-Allow-Headers","X-Kyoppie-Access-Token");
    res.append("Access-Control-Max-Age","86400")
    next();
})
app.options('*',function(req,res){
    res.end();
})
app.post('*',function(req,res,next){
    var log = new models.logs();
    log.ipaddr = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    log.path = req.originalUrl;
    res.send_nolog = res.send;
    res.code_nolog = res.code;
    res.code = function(code){
        var obj_ = res.code_nolog(code);
        return {
            send:function(obj){
                obj_.send(obj)
                try{
                    log.response = JSON.stringify(obj);
                    log.save();
                }catch(e){}
            }
        }
    }
    res.send = function(obj){
        res.send_nolog(obj)
        try{
            log.response = JSON.stringify(obj);
            log.save();
        }catch(e){}
    }
    next();
})
function msgpackHack(req,res,next){
    res.send_nomsgpackhack = res.send;
    res.send = function(obj){
        obj = JSON.parse(JSON.stringify(obj));
        res.set("Content-Type","application/x-msgpack")
        res.send_nomsgpackhack(msgpack.encode(obj));
    }
    res.code_nomsgpackhack = res.code;
    res.code = function(code){
        res.set("Content-Type","application/x-msgpack")
        var obj_ = res.code_nomsgpackhack(code);
        return {
            send:function(obj){
                obj = JSON.parse(JSON.stringify(obj))
                obj_.send(encode(msgpack.encode(obj)))
            }
        }
    }
    next();
}
function yamlHack(req,res,next){
    res.send_noyamlhack = res.send;
    res.send = function(obj){
        obj = JSON.parse(JSON.stringify(obj));
        res.set("Content-Type","text/yaml")
        res.send_noyamlhack(yaml.stringify(obj));
    }
    res.code_nomsgpackhack = res.code;
    res.code = function(code){
        res.set("Content-Type","text/yaml")
        var obj_ = res.code_nomsgpackhack(code);
        return {
            send:function(obj){
                obj = JSON.parse(JSON.stringify(obj))
                obj_.send(encode(yaml.stringify(obj)))
            }
        }
    }
    next();
}
var routes = require("./routes")
routes.rest.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var method = route.method;
    var path = route.name;
    var authFunc = tokenAuth(route,login)
    var checkSuspended = function(req,res,next){
        if(req.method == "POST" && login && req.token.user.isSuspended){
            res.status(403).send({result:false,error:"this-user-is-suspended"})
        } else {
            next();
        }
    }
    if(route.file){
        app[method](path,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".msgpack",msgpackHack,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".yaml",yamlHack,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
    }else{
        app[method](path,authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".msgpack",msgpackHack,authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".yaml",yamlHack,authFunc,checkSuspended,require("./handlers/web"+path));
    }
})
var ws_route = {};
routes.websocket.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var path = route.name;
    ws_route[path] = route;
    ws_route[path]["login"] = login;
    ws_route[path]["callback"] = require("./handlers/ws"+path)
})
app.all("*",function(req,res){
    // not found
    res.status(404).send({result:false,error:"not-found-api"})
})
wss.on("connection",function(ws){
    var location = url_module.parse(ws.upgradeReq.url,true);
    var url = location.pathname;
    ws.sendJSON = function(json){
        ws.send(JSON.stringify(json))
    }
    if(!ws_route[url]){
        ws.sendJSON({result:false,error:"api-not-found"})
        ws.close();
        return
    }
    console.log(ws_route)
    if(ws_route[url].login){
        if(location.query.access_token){
            models.access_tokens.findOne({
                secret:location.query.access_token
            }).populate("app user").then(function(token){
                console.log(token)
                if(token){
                    ws.token=token;
                    ws_route[url].callback(ws);
                } else {
                    ws.sendJSON({result:false,error:"please-auth"})
                    ws.close()
                    return
                }
            },function(){
                ws.send(JSON.strigify({response:false,error:"server-side-auth-error"}))
                ws.close()
                return
            })
        } else {
            ws.sendJSON({result:false,error:"please-auth"})
            ws.close()
            return
        }
    } else {
        ws_route[url].callback(ws);
    }
})
server.on("request",app);
server.listen(4005,function(){
    console.log("listen for "+server.address().port+" port");
})<commit_msg>.jsonでアクセスできるように<commit_after>var express = require("express")
var server = require("http").createServer();
var wss = new require("ws").Server({server});
var app = express();
var models = require("./models")
var bodyParser = require("body-parser")
var url_module = require("url")
var tokenAuth = require("./utils/tokenAuth")
var multer = require("multer")()
var models = require("./models")
var msgpack = require("msgpack5")()
var yaml = require("yamljs")

console.log("###################")
console.log("### Kyoppie API ###")
console.log("###################")
console.log("Repository: https://github.com/kyoppie/kyoppie-api")

app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(function(req,res,next){
    res.append("Access-Control-Allow-Origin","*")
    res.append("Access-Control-Allow-Method","GET, POST, OPTIONS");
    res.append("Access-Control-Allow-Headers","X-Kyoppie-Access-Token");
    res.append("Access-Control-Max-Age","86400")
    next();
})
app.options('*',function(req,res){
    res.end();
})
app.post('*',function(req,res,next){
    var log = new models.logs();
    log.ipaddr = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    log.path = req.originalUrl;
    res.send_nolog = res.send;
    res.code_nolog = res.code;
    res.code = function(code){
        var obj_ = res.code_nolog(code);
        return {
            send:function(obj){
                obj_.send(obj)
                try{
                    log.response = JSON.stringify(obj);
                    log.save();
                }catch(e){}
            }
        }
    }
    res.send = function(obj){
        res.send_nolog(obj)
        try{
            log.response = JSON.stringify(obj);
            log.save();
        }catch(e){}
    }
    next();
})
function msgpackHack(req,res,next){
    res.send_nomsgpackhack = res.send;
    res.send = function(obj){
        obj = JSON.parse(JSON.stringify(obj));
        res.set("Content-Type","application/x-msgpack")
        res.send_nomsgpackhack(msgpack.encode(obj));
    }
    res.code_nomsgpackhack = res.code;
    res.code = function(code){
        res.set("Content-Type","application/x-msgpack")
        var obj_ = res.code_nomsgpackhack(code);
        return {
            send:function(obj){
                obj = JSON.parse(JSON.stringify(obj))
                obj_.send(encode(msgpack.encode(obj)))
            }
        }
    }
    next();
}
function yamlHack(req,res,next){
    res.send_noyamlhack = res.send;
    res.send = function(obj){
        obj = JSON.parse(JSON.stringify(obj));
        res.set("Content-Type","text/yaml")
        res.send_noyamlhack(yaml.stringify(obj));
    }
    res.code_nomsgpackhack = res.code;
    res.code = function(code){
        res.set("Content-Type","text/yaml")
        var obj_ = res.code_nomsgpackhack(code);
        return {
            send:function(obj){
                obj = JSON.parse(JSON.stringify(obj))
                obj_.send(encode(yaml.stringify(obj)))
            }
        }
    }
    next();
}
var routes = require("./routes")
routes.rest.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var method = route.method;
    var path = route.name;
    var authFunc = tokenAuth(route,login)
    var checkSuspended = function(req,res,next){
        if(req.method == "POST" && login && req.token.user.isSuspended){
            res.status(403).send({result:false,error:"this-user-is-suspended"})
        } else {
            next();
        }
    }
    if(route.file){
        app[method](path,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".json",multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".msgpack",msgpackHack,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".yaml",yamlHack,multer.single("file"),authFunc,checkSuspended,require("./handlers/web"+path));
    }else{
        app[method](path,authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".json",authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".msgpack",msgpackHack,authFunc,checkSuspended,require("./handlers/web"+path));
        app[method](path+".yaml",yamlHack,authFunc,checkSuspended,require("./handlers/web"+path));
    }
})
var ws_route = {};
routes.websocket.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var path = route.name;
    ws_route[path] = route;
    ws_route[path]["login"] = login;
    ws_route[path]["callback"] = require("./handlers/ws"+path)
})
app.all("*",function(req,res){
    // not found
    res.status(404).send({result:false,error:"not-found-api"})
})
wss.on("connection",function(ws){
    var location = url_module.parse(ws.upgradeReq.url,true);
    var url = location.pathname;
    ws.sendJSON = function(json){
        ws.send(JSON.stringify(json))
    }
    if(!ws_route[url]){
        ws.sendJSON({result:false,error:"api-not-found"})
        ws.close();
        return
    }
    console.log(ws_route)
    if(ws_route[url].login){
        if(location.query.access_token){
            models.access_tokens.findOne({
                secret:location.query.access_token
            }).populate("app user").then(function(token){
                console.log(token)
                if(token){
                    ws.token=token;
                    ws_route[url].callback(ws);
                } else {
                    ws.sendJSON({result:false,error:"please-auth"})
                    ws.close()
                    return
                }
            },function(){
                ws.send(JSON.strigify({response:false,error:"server-side-auth-error"}))
                ws.close()
                return
            })
        } else {
            ws.sendJSON({result:false,error:"please-auth"})
            ws.close()
            return
        }
    } else {
        ws_route[url].callback(ws);
    }
})
server.on("request",app);
server.listen(4005,function(){
    console.log("listen for "+server.address().port+" port");
})<|endoftext|>