<commit_before>var UI = {};

UI.init = function(){
	//initialise
	UI._lockAll();

	//update all the lists
	UI._updateParserList();
	UI._lockAll();  //lock stuff

	UI._updatePlayerList();
	UI._lockAll();  //lock stuff

	UI._updateDataSetsList();
	UI._lockAll();  //lock stuff

	//bind all the eventsl
	UI._elements.play.click(function(){
		UI.play();
	});

	UI._elements.stop.click(function(){
		UI.stop();
	});

	UI._elements.PlayerConfig.click(function(){
		UI.PlayerConfig();
	});

	UI._elements.playerSelect.change(function(){
		UI._playerUpdated();
	});

	UI._elements.parserSelect.change(function(){
		UI._parserUpdated();
	});

	UI._elements.instrumentSelect.change(function(){
		UI._instrumentUpdated();
	});

	UI._elements.load.click(function(){
		UI._dataSetUpdated();
	})

	if(window.location.hash == "#right"){
		$("body").addClass("right");
	} else {
		$("body").addClass("left");
	}

	UI._loadInstruments(function(){
		UI._stopState();
		window.parent.postMessage('loaded', '*')
	});
};

UI.play = function(){
	//called when hitting the start button
	UI._lockAll();

	var noSpaces = UI._elements.data.val().replace(/\s+/g, '');

	UI._ticker = new Ticker(noSpaces, $("div.visualiser"), UI._config);

	UI._startState(); //once we have started
	UI._ticker.start();
};

UI.stop = function(){
	//called when hitting the stop button
	UI._lockAll();
	UI._ticker.stop();
	UI._stopState();
};

UI.PlayerConfig = function(){
	//called when hitting the Parser Config Button
};

UI._updateParserList = function(){
	//update the parser list
	UI._lockAll();
	UI._elements.parserSelect.empty();

	for(var key in Parser.Parsers){
		UI._elements.parserSelect.append(
			$("<option>")
			.attr("value", key)
			.text(Parser.Parsers[key].desc)
		);
	}

	UI._parserUpdated();
};

UI._parserUpdated = function(){
	//called when the parser is updated
	UI._lockAll();

	UI._config.parser = UI._elements.parserSelect.val();
	//load the default config for the parser

	UI._stopState();
}

UI._updatePlayerList = function(){
	//update the player list

	UI._lockAll();
	UI._elements.playerSelect.empty();

	for(var key in Player.Players){
		UI._elements.playerSelect.append(
			$("<option>")
			.attr("value", key)
			.text(Player.Players[key].desc)
		);
	}

	UI._playerUpdated();
};

UI._playerUpdated = function(){
	//called when the player is updated
	UI._lockAll();
	UI._config.player = UI._elements.playerSelect.val();
	UI._updateInstrumentList();
	UI._stopState();
};

UI._dataSetUpdated = function(){
	//data set updated
	UI._elements.data.val(UI._elements.dataSetSelect.val());
};

UI._updateInstrumentList = function(){
	//updates the instrument list

	UI._lockAll();
	UI._elements.instrumentSelect.empty();

	var font_options = Player.Players[UI._config.player].font_options;
	var did = false;

	for(var key in font_options){
		UI._elements.instrumentSelect.append(
			$("<option>")
			.attr("value", key)
			.text(font_options[key])
		);
		did = true;
	}

	if(!did){
		UI._elements.instrumentSelect.append(
			$("<option>")
			.attr("value", "")
			.text("N/A")
		);
	}

	UI._instrumentUpdated();
};

UI._updateDataSetsList = function(){
	var Presets = {
		"Normal Hemoglobin": "ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCCGTTACT",
		"Sickle Cell Hemoglobin": "ATGGTGCACCTGACTCCTGTGGAGAAGTCTGCCGTTACT"
	};

	UI._elements.dataSetSelect.empty();

	for(var key in Presets){
		UI._elements.dataSetSelect.append($("<option>").val(Presets[key]).text(key))
	}
}

UI._instrumentUpdated = function(){
	//called when the instrument is updated
	UI._lockAll();
	UI._config.instrument = UI._elements.instrumentSelect.val();
	UI._stopState();
}

UI._lockAll = function(){
	//locks the UI in the playing state

	UI._elements.play.attr("disabled", "disabled");
	UI._elements.stop.attr("disabled", "disabled");
	UI._elements.PlayerConfig.attr("disabled", "disabled");
	UI._elements.parserSelect.attr("disabled", "disabled");
	UI._elements.playerSelect.attr("disabled", "disabled");
	UI._elements.instrumentSelect.attr("disabled", "disabled");

	UI._elements.dataSetSelect.attr("disabled", "disabled");
	UI._elements.load.attr("disabled", "disabled");
};

UI._unLockAll = function(){
	//locks the UI in the stopped state

	UI._elements.play.removeAttr("disabled");
	UI._elements.stop.removeAttr("disabled");
	UI._elements.PlayerConfig.removeAttr("disabled");
	UI._elements.parserSelect.removeAttr("disabled");
	UI._elements.playerSelect.removeAttr("disabled");
	UI._elements.instrumentSelect.removeAttr("disabled");

	UI._elements.dataSetSelect.removeAttr("disabled");
	UI._elements.load.removeAttr("disabled");

	if(UI._elements.instrumentSelect.val() == ""){
		// N/A
		UI._elements.instrumentSelect.attr("disabled", "disabled");
	}
};

UI._stopState = function(){
	UI._unLockAll();
	UI._elements.stop.attr("disabled", "disabled");
}

UI._startState = function(){
	UI._lockAll();
	UI._elements.stop.removeAttr("disabled");
}

UI._elements = {
	"data": $("textarea.data"),
	"play": $(".play"),
	"stop": $(".stop"),
	"load": $(".load"),
	"PlayerConfig": $(".options.player"),
	"parserSelect": $(".selectable.parser"),
	"playerSelect": $(".selectable.player"),
	"instrumentSelect": $(".selectable.instrument"),
	"dataSetSelect": $(".selectable.presets")
};

UI._config = {
	"player": undefined,
	"parser": undefined,
	"instrument": undefined,
	"content": undefined,
	"tickLength": 100,
	"baseVolume": 127
};

UI._loadInstruments = function(cb){

	//load all the instruments

	var instruments = ["marimba", "acoustic_grand_piano", "violin", "choir_aahs", "xylophone", "acoustic_bass", "synth_drum", "fx_6_goblins"];

	MIDI.loadPlugin({
		soundfontUrl: "./../lib/midi/soundfont/",
		instruments: instruments,
		callback: cb
	});
}<commit_msg>Added more presets<commit_after>var UI = {};

UI.init = function(){
	//initialise
	UI._lockAll();

	//update all the lists
	UI._updateParserList();
	UI._lockAll();  //lock stuff

	UI._updatePlayerList();
	UI._lockAll();  //lock stuff

	UI._updateDataSetsList();
	UI._lockAll();  //lock stuff

	//bind all the eventsl
	UI._elements.play.click(function(){
		UI.play();
	});

	UI._elements.stop.click(function(){
		UI.stop();
	});

	UI._elements.PlayerConfig.click(function(){
		UI.PlayerConfig();
	});

	UI._elements.playerSelect.change(function(){
		UI._playerUpdated();
	});

	UI._elements.parserSelect.change(function(){
		UI._parserUpdated();
	});

	UI._elements.instrumentSelect.change(function(){
		UI._instrumentUpdated();
	});

	UI._elements.load.click(function(){
		UI._dataSetUpdated();
	})

	if(window.location.hash == "#right"){
		$("body").addClass("right");
	} else {
		$("body").addClass("left");
	}

	UI._loadInstruments(function(){
		UI._stopState();
		window.parent.postMessage('loaded', '*')
	});
};

UI.play = function(){
	//called when hitting the start button
	UI._lockAll();

	var noSpaces = UI._elements.data.val().replace(/\s+/g, '');

	UI._ticker = new Ticker(noSpaces, $("div.visualiser"), UI._config);

	UI._startState(); //once we have started
	UI._ticker.start();
};

UI.stop = function(){
	//called when hitting the stop button
	UI._lockAll();
	UI._ticker.stop();
	UI._stopState();
};

UI.PlayerConfig = function(){
	//called when hitting the Parser Config Button
};

UI._updateParserList = function(){
	//update the parser list
	UI._lockAll();
	UI._elements.parserSelect.empty();

	for(var key in Parser.Parsers){
		UI._elements.parserSelect.append(
			$("<option>")
			.attr("value", key)
			.text(Parser.Parsers[key].desc)
		);
	}

	UI._parserUpdated();
};

UI._parserUpdated = function(){
	//called when the parser is updated
	UI._lockAll();

	UI._config.parser = UI._elements.parserSelect.val();
	//load the default config for the parser

	UI._stopState();
}

UI._updatePlayerList = function(){
	//update the player list

	UI._lockAll();
	UI._elements.playerSelect.empty();

	for(var key in Player.Players){
		UI._elements.playerSelect.append(
			$("<option>")
			.attr("value", key)
			.text(Player.Players[key].desc)
		);
	}

	UI._playerUpdated();
};

UI._playerUpdated = function(){
	//called when the player is updated
	UI._lockAll();
	UI._config.player = UI._elements.playerSelect.val();
	UI._updateInstrumentList();
	UI._stopState();
};

UI._dataSetUpdated = function(){
	//data set updated
	UI._elements.data.val(UI._elements.dataSetSelect.val());
};

UI._updateInstrumentList = function(){
	//updates the instrument list

	UI._lockAll();
	UI._elements.instrumentSelect.empty();

	var font_options = Player.Players[UI._config.player].font_options;
	var did = false;

	for(var key in font_options){
		UI._elements.instrumentSelect.append(
			$("<option>")
			.attr("value", key)
			.text(font_options[key])
		);
		did = true;
	}

	if(!did){
		UI._elements.instrumentSelect.append(
			$("<option>")
			.attr("value", "")
			.text("N/A")
		);
	}

	UI._instrumentUpdated();
};

UI._updateDataSetsList = function(){
	var Presets = {
		"Normal Hemoglobin": "ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCCGTTACT",
		"Sickle Cell Hemoglobin": "ATGGTGCACCTGACTCCTGTGGAGAAGTCTGCCGTTACT",
		"Für Elise": "GCCGCTGCCGCTGCCGTCGCGGCAGTTGCAGCCGTTGTCGCCGTTGTCGCAGCCGCTGCCGCTGCCGTCGCGGCAGTTGCAGCCGTTGTCGCCGCAGTCGTTGTCGCAGCGGCCTAGGCCGCCGCGGCCGCCGCGGCAGCCGCGGCAGCCGCCGCTGCCGCTGCCGCCGCGGCAGTTGCAGCCGTTGTCGCCGTTGTCGCAGCCGCTGCCGCTGCCGTCGCGGCAGTTGCAGCCGTTGTCGCCGCAGTCGTT",
		"Treacher Collins Syndrome (healthy)": "GGAGGACTCAGAGAGCAGCAGCGAGGAGTCATCTGACAGTGAG",
		"Treacher Collins Syndrome (ill)": "GGAGGACTCAGAGCAGCAGCGAGGAGTCATCTGACAGTGAG"
	};

	UI._elements.dataSetSelect.empty();

	for(var key in Presets){
		UI._elements.dataSetSelect.append($("<option>").val(Presets[key]).text(key))
	}
}

UI._instrumentUpdated = function(){
	//called when the instrument is updated
	UI._lockAll();
	UI._config.instrument = UI._elements.instrumentSelect.val();
	UI._stopState();
}

UI._lockAll = function(){
	//locks the UI in the playing state

	UI._elements.play.attr("disabled", "disabled");
	UI._elements.stop.attr("disabled", "disabled");
	UI._elements.PlayerConfig.attr("disabled", "disabled");
	UI._elements.parserSelect.attr("disabled", "disabled");
	UI._elements.playerSelect.attr("disabled", "disabled");
	UI._elements.instrumentSelect.attr("disabled", "disabled");

	UI._elements.dataSetSelect.attr("disabled", "disabled");
	UI._elements.load.attr("disabled", "disabled");
};

UI._unLockAll = function(){
	//locks the UI in the stopped state

	UI._elements.play.removeAttr("disabled");
	UI._elements.stop.removeAttr("disabled");
	UI._elements.PlayerConfig.removeAttr("disabled");
	UI._elements.parserSelect.removeAttr("disabled");
	UI._elements.playerSelect.removeAttr("disabled");
	UI._elements.instrumentSelect.removeAttr("disabled");

	UI._elements.dataSetSelect.removeAttr("disabled");
	UI._elements.load.removeAttr("disabled");

	if(UI._elements.instrumentSelect.val() == ""){
		// N/A
		UI._elements.instrumentSelect.attr("disabled", "disabled");
	}
};

UI._stopState = function(){
	UI._unLockAll();
	UI._elements.stop.attr("disabled", "disabled");
}

UI._startState = function(){
	UI._lockAll();
	UI._elements.stop.removeAttr("disabled");
}

UI._elements = {
	"data": $("textarea.data"),
	"play": $(".play"),
	"stop": $(".stop"),
	"load": $(".load"),
	"PlayerConfig": $(".options.player"),
	"parserSelect": $(".selectable.parser"),
	"playerSelect": $(".selectable.player"),
	"instrumentSelect": $(".selectable.instrument"),
	"dataSetSelect": $(".selectable.presets")
};

UI._config = {
	"player": undefined,
	"parser": undefined,
	"instrument": undefined,
	"content": undefined,
	"tickLength": 100,
	"baseVolume": 127
};

UI._loadInstruments = function(cb){

	//load all the instruments

	var instruments = ["marimba", "acoustic_grand_piano", "violin", "choir_aahs", "xylophone", "acoustic_bass", "synth_drum", "fx_6_goblins"];

	MIDI.loadPlugin({
		soundfontUrl: "./../lib/midi/soundfont/",
		instruments: instruments,
		callback: cb
	});
}<|endoftext|>


<commit_before>/**
 * Created by zzn on 2015-05-05.
 * Contains the MVC framework working for a PostItem
 *
 * Requires jQuery
 */

var PostItemMVC = (function ($, wx, zHelper) {
    "use strict";
    var CONST_SPREADSHEET_URL = "https://spreadsheets.google.com/feeds/list/1vzugrYLpgXmFODqysSx331Lhq8LpDQGJ4sQtwSMrtV4/1/public/values?alt=json";
    var CONST_FIELD_KEYS = {
        xq: "gsx$需求类别",
        qssj: "gsx$预计起始日期超过这个日期本条信息失效",
        qy: "gsx$区域",
        ybhzcs: "gsx$邮编或者城市",
        yqjg: "gsx$预期价格美元每月",
        grjs: "gsx$租房需求介绍和自我介绍",
        wxId: "gsx$微信号",
        xb: "gsx$性别",
        dhyx: "gsx$其他联系方式电话邮箱等",
        fbsj: "gsx$timestamp",
        ltst: "gsx$shorttermorlongterm",
        entryid: "gsx$entryid"
    };

    var CONST_FIELDS = [
        'xq', 'qssj', 'qy', 'ybhzcs', 'yqjg', 'grjs',
        'wxId', 'xb', 'dhyx', 'fbsj', 'ltst'
    ];

    var CONST_VALUE_ID_PREFIX = "#value_";
    var CONST_ITEM_TEMPLATE_ID = "#value_panel_template";
    var CONST_DOMAIN_NAME = "rent.zzn.im";
    /**
     * Class definition of Model
     * @constructor
     */
    var Model = function () {
        this.clearData(); // init with clear data
    };

    /**
     *
     * Creates a view as a clone of template
     * @constructor
     */
    var ItemView = function (guid) {
        this.guid_ = guid;
        this.templateClone_ = $(CONST_ITEM_TEMPLATE_ID).clone();
        this.guidLink_ = "http://" + CONST_DOMAIN_NAME + "/?" + $.param({"guid": guid});
    };

    var PanelView = function () {
        this.panelDom_ = $("#value_panel_parent");
    };

    /**
     * Class definition of Controller
     * @constructor
     */
    var Controller = function () {
        this.model_ = new Model();
        this.panelView_ = new PanelView();
    };

    // Set up cors proxy for jQuery
    $.ajaxPrefilter(function (options) {
        if (options.crossDomain && jQuery.support.cors) {
            var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
            options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
        }
    });

    Model.prototype.loadDataAsync = function (callback) {
        var that = this;
        $.get(CONST_SPREADSHEET_URL, function (data) {
            zHelper.log("loaded data from CORS proxy");
            that.cachedData_ = {}; //update data;
            data.feed.entry.forEach(function (row) {
                var guid = row[CONST_FIELD_KEYS.entryid]["$t"] || "N/A";
                var datum = {};
                CONST_FIELDS.forEach(function (fieldName) {
                    datum[fieldName] = row[CONST_FIELD_KEYS[fieldName]]["$t"] || "N/A";
                });
                that.cachedData_[guid] = datum;
                that.guidArray_.push(guid);
            });
            callback(data); // done
        });
    };

    Model.prototype.clearData = function () {
        this.cachedData_ = {};
        this.guidArray_ = [];
    };

    Model.prototype.getGuidArray = function () {
        return this.guidArray_;
    };

    Model.prototype.getFieldData = function (fieldName, guid) {
        return this.cachedData_[guid][fieldName];
    };

    /**
     * Add Guid Related Links
     * @param guid
     * @private
     */
    ItemView.prototype.decrorate_ = function () {
        var guid = this.guid_;
        var template = this.templateClone_;
        var guidLink = this.guidLink_;
        template.find("#qrcode").qrcode(guidLink);
        template.find("#row_link").attr("href", guidLink);
        template.find("#btn_share").attr("data-guid", guid);
        template.find("#btn_like").attr("data-guid", guid);
        template.show();
    };

    /**
     *
     * @param should boolean to indicate show(true) or hide(false)
     */
    ItemView.prototype.shouldShowContactInfo = function (should, model) {
        var that = this;
        var template = this.templateClone_;
        if (should) {
            template.find("#btn_show_wxId").hide();
            template.find("#btn_show_dhyx").hide();
        } else {
            template.find("#value_wxId").hide();
            template.find("#value_dhyx").hide();

            template.find("#value_wxId").hide();
            template.find("#btn_show_wxId").click(function () {
                template.find("#btn_show_wxId").hide();
                template.find("#value_wxId").show();
            });
            template.find("#btn_show_dhyx").click(function () {
                template.find("#btn_show_dhyx").hide();
                template.find("#value_dhyx").show();
            });

        }
    };

    ItemView.prototype.displayData = function (model) {
        var template = this.templateClone_;
        var guid = this.guid_;
        var xq = model.getFieldData("xq", guid);
        if (xq == "出租") {
            template.addClass("panel-success");
        } else if (xq == "求租") {
            template.addClass("panel-primary");
        } else if (xq == "找室友") {
            template.addClass("panel-warning");
        }
        CONST_FIELDS.forEach(function (fieldName) {
            template.find(CONST_VALUE_ID_PREFIX + fieldName).text(model.getFieldData(fieldName, guid));
        });

        // Set up Id of template
        template.attr("id", "value_panel" + guid);
        this.decrorate_();
    };
    ItemView.prototype.getDom = function () {
        return this.templateClone_;
    };

    ItemView.prototype.configureWeChat_ = function(model){
        zHelper.logAlert("clicked configure wechat!");
        var guidLink = this.guidLink_;
        var guid = this.guid_;
        var xq = model.getFieldData("xq", guid);
        var title, link, imgUrl, desc;
        if (xq == "出租") {
            imgUrl = "http://" + CONST_DOMAIN_NAME + "/img/logo-v1-green-1024sq2.jpg";
        } else if (xq == "求租") {
            imgUrl = "http://" + CONST_DOMAIN_NAME + "/img/logo-v1-blue-1024sq2.jpg";
        } else if (xq == "找室友") {
            imgUrl = "http://" + CONST_DOMAIN_NAME +"/img/logo-v1-yellow-1024sq2.jpg";
        }
        title = model.getFieldData("xq", guid) +
            model.getFieldData("qy", guid) + "，时间是" +
            model.getFieldData("qssj", guid) + "左右开始，求分享！";
        link = guidLink;
        desc = model.getFieldData("grjs", guid);
        var wxData = {
            title: title,
            link: link,
            imgUrl: imgUrl,
            desc: desc,
            trigger: function (res) {
                zHelper.logAlert('用户点击发送给朋友');
            },
            success: function (ret) {
                zHelper.logAlert("shared!");
                zHelper.logAlert("ret=" + JSON.stringify(ret));
            },
            cancel: function (ret) {
                zHelper.logAlert("cancel share!");
                zHelper.logAlert("ret=" + JSON.stringify(ret));
            }
        };
        wx.onMenuShareAppMessage(wxData);
        wx.onMenuShareTimeline(wxData);
        zHelper.logAlert('已注册获取“分享到朋友圈”状态事件');
        zHelper.logAlert("XXX 777 X");

    };
    PanelView.prototype.addChild = function (item) {
        this.panelDom_.append(item);
    };

    PanelView.prototype.clearChildren = function () {
        this.panelDom_.empty();
    };

    Controller.prototype.initAsync = function (callback) {
        this.model_.loadDataAsync(callback);
    };

    Controller.prototype.showAllItems = function () {
        var that = this;
        this.panelView_.clearChildren();
        this.model_.getGuidArray().forEach(function (guid) {
            var item = new ItemView(guid);
            item.displayData(that.model_, guid);
            item.shouldShowContactInfo(false, that.model_);
            that.panelView_.addChild(item.getDom());

        });
    };

    /**
     *
     * @param guid The GUID of a given listing post
     */
    Controller.prototype.showItemByGuid = function (guid) {
        this.panelView_.clearChildren();
        var that = this;
        var item = new ItemView(guid);
        item.displayData(this.model_, guid);
        item.shouldShowContactInfo(true, this.model_);

        wx.ready(function(res){
            zHelper.log(res);
            wx.checkJsApi({
                jsApiList: [
                    "onMenuShareTimeline",
                    "onMenuShareAppMessage"
                ],
                success: function (res) {
                    zHelper.logAlert("wxCheckJsApi, success, configuring WeChat");
                    zHelper.log(JSON.stringify(res));
                    // TODO(zzn):
                    // uncomment update it here
                    item.configureWeChat_(that.model_);
                },
                fail: function (res) {
                    zHelper.logAlert("wxCheckJsApi, faile");
                    zHelper.log(JSON.stringify(res));
                }
            });

        });

        zHelper.log("XXX after setting wechat");
        this.panelView_.addChild(item.getDom());
    };

    return {
        Controller: Controller
    };
})($, wx, zHelper);<commit_msg>Update<commit_after>/**
 * Created by zzn on 2015-05-05.
 * Contains the MVC framework working for a PostItem
 *
 * Requires jQuery
 */

var PostItemMVC = (function ($, wx, zHelper) {
    "use strict";
    var CONST_SPREADSHEET_URL = "https://spreadsheets.google.com/feeds/list/1vzugrYLpgXmFODqysSx331Lhq8LpDQGJ4sQtwSMrtV4/1/public/values?alt=json";
    var CONST_FIELD_KEYS = {
        xq: "gsx$需求类别",
        qssj: "gsx$预计起始日期超过这个日期本条信息失效",
        qy: "gsx$区域",
        ybhzcs: "gsx$邮编或者城市",
        yqjg: "gsx$预期价格美元每月",
        grjs: "gsx$租房需求介绍和自我介绍",
        wxId: "gsx$微信号",
        xb: "gsx$性别",
        dhyx: "gsx$其他联系方式电话邮箱等",
        fbsj: "gsx$timestamp",
        ltst: "gsx$shorttermorlongterm",
        entryid: "gsx$entryid"
    };

    var CONST_FIELDS = [
        'xq', 'qssj', 'qy', 'ybhzcs', 'yqjg', 'grjs',
        'wxId', 'xb', 'dhyx', 'fbsj', 'ltst'
    ];

    var CONST_VALUE_ID_PREFIX = "#value_";
    var CONST_ITEM_TEMPLATE_ID = "#value_panel_template";
    var CONST_DOMAIN_NAME = "rent.zzn.im";
    /**
     * Class definition of Model
     * @constructor
     */
    var Model = function () {
        this.clearData(); // init with clear data
    };

    /**
     *
     * Creates a view as a clone of template
     * @constructor
     */
    var ItemView = function (guid) {
        this.guid_ = guid;
        this.templateClone_ = $(CONST_ITEM_TEMPLATE_ID).clone();
        this.guidLink_ = "http://" + CONST_DOMAIN_NAME + "/?" + $.param({"guid": guid});
    };

    var PanelView = function () {
        this.panelDom_ = $("#value_panel_parent");
    };

    /**
     * Class definition of Controller
     * @constructor
     */
    var Controller = function () {
        this.model_ = new Model();
        this.panelView_ = new PanelView();
    };

    // Set up cors proxy for jQuery
    $.ajaxPrefilter(function (options) {
        if (options.crossDomain && jQuery.support.cors) {
            var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
            options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
        }
    });

    Model.prototype.loadDataAsync = function (callback) {
        var that = this;
        $.get(CONST_SPREADSHEET_URL, function (data) {
            zHelper.log("loaded data from CORS proxy");
            that.cachedData_ = {}; //update data;
            data.feed.entry.forEach(function (row) {
                var guid = row[CONST_FIELD_KEYS.entryid]["$t"] || "N/A";
                var datum = {};
                CONST_FIELDS.forEach(function (fieldName) {
                    datum[fieldName] = row[CONST_FIELD_KEYS[fieldName]]["$t"] || "N/A";
                });
                that.cachedData_[guid] = datum;
                that.guidArray_.push(guid);
            });
            callback(data); // done
        });
    };

    Model.prototype.clearData = function () {
        this.cachedData_ = {};
        this.guidArray_ = [];
    };

    Model.prototype.getGuidArray = function () {
        return this.guidArray_;
    };

    Model.prototype.getFieldData = function (fieldName, guid) {
        return this.cachedData_[guid][fieldName];
    };

    /**
     * Add Guid Related Links
     * @param guid
     * @private
     */
    ItemView.prototype.decrorate_ = function () {
        var guid = this.guid_;
        var template = this.templateClone_;
        var guidLink = this.guidLink_;
        template.find("#qrcode").qrcode(guidLink);
        template.find("#row_link").attr("href", guidLink);
        template.find("#btn_share").attr("data-guid", guid);
        template.find("#btn_like").attr("data-guid", guid);
        template.show();
    };

    /**
     *
     * @param should boolean to indicate show(true) or hide(false)
     */
    ItemView.prototype.shouldShowContactInfo = function (should, model) {
        var that = this;
        var template = this.templateClone_;
        if (should) {
            template.find("#btn_show_wxId").hide();
            template.find("#btn_show_dhyx").hide();
        } else {
            template.find("#value_wxId").hide();
            template.find("#value_dhyx").hide();

            template.find("#value_wxId").hide();
            template.find("#btn_show_wxId").click(function () {
                template.find("#btn_show_wxId").hide();
                template.find("#value_wxId").show();
            });
            template.find("#btn_show_dhyx").click(function () {
                template.find("#btn_show_dhyx").hide();
                template.find("#value_dhyx").show();
            });

        }
    };

    ItemView.prototype.displayData = function (model) {
        var template = this.templateClone_;
        var guid = this.guid_;
        var xq = model.getFieldData("xq", guid);
        if (xq == "出租") {
            template.addClass("panel-success");
        } else if (xq == "求租") {
            template.addClass("panel-primary");
        } else if (xq == "找室友") {
            template.addClass("panel-warning");
        }
        CONST_FIELDS.forEach(function (fieldName) {
            template.find(CONST_VALUE_ID_PREFIX + fieldName).text(model.getFieldData(fieldName, guid));
        });

        // Set up Id of template
        template.attr("id", "value_panel" + guid);
        this.decrorate_();
    };
    ItemView.prototype.getDom = function () {
        return this.templateClone_;
    };

    ItemView.prototype.configureWeChat_ = function(model){
        zHelper.logAlert("clicked configure wechat!");
        var guidLink = this.guidLink_;
        var guid = this.guid_;
        var xq = model.getFieldData("xq", guid);
        var title, link, imgUrl, desc;
        if (xq == "出租") {
            imgUrl = "http://" + CONST_DOMAIN_NAME + "/img/logo-v1-green-1024sq2.jpg";
        } else if (xq == "求租") {
            imgUrl = "http://" + CONST_DOMAIN_NAME + "/img/logo-v1-blue-1024sq2.jpg";
        } else if (xq == "找室友") {
            imgUrl = "http://" + CONST_DOMAIN_NAME +"/img/logo-v1-yellow-1024sq2.jpg";
        }
        title = model.getFieldData("xq", guid) +
            model.getFieldData("qy", guid) + "，时间是" +
            model.getFieldData("qssj", guid) + "左右开始，求分享！";
        link = guidLink;
        desc = "情况介绍：" + model.getFieldData("grjs", guid);
        var wxData = {
            title: title,
            link: link,
            imgUrl: imgUrl,
            desc: desc,
            trigger: function (res) {
                zHelper.logAlert('用户点击发送给朋友');
            },
            success: function (ret) {
                zHelper.logAlert("shared!");
                zHelper.logAlert("ret=" + JSON.stringify(ret));
            },
            cancel: function (ret) {
                zHelper.logAlert("cancel share!");
                zHelper.logAlert("ret=" + JSON.stringify(ret));
            }
        };
        wx.onMenuShareAppMessage(wxData);
        wx.onMenuShareTimeline(wxData);
        zHelper.logAlert('已注册获取“分享到朋友圈”状态事件');
        zHelper.logAlert("XXX 777 X");

    };
    PanelView.prototype.addChild = function (item) {
        this.panelDom_.append(item);
    };

    PanelView.prototype.clearChildren = function () {
        this.panelDom_.empty();
    };

    Controller.prototype.initAsync = function (callback) {
        this.model_.loadDataAsync(callback);
    };

    Controller.prototype.showAllItems = function () {
        var that = this;
        this.panelView_.clearChildren();
        this.model_.getGuidArray().forEach(function (guid) {
            var item = new ItemView(guid);
            item.displayData(that.model_, guid);
            item.shouldShowContactInfo(false, that.model_);
            that.panelView_.addChild(item.getDom());

        });
    };

    /**
     *
     * @param guid The GUID of a given listing post
     */
    Controller.prototype.showItemByGuid = function (guid) {
        this.panelView_.clearChildren();
        var that = this;
        var item = new ItemView(guid);
        item.displayData(this.model_, guid);
        item.shouldShowContactInfo(true, this.model_);

        wx.ready(function(res){
            zHelper.log(res);
            wx.checkJsApi({
                jsApiList: [
                    "onMenuShareTimeline",
                    "onMenuShareAppMessage"
                ],
                success: function (res) {
                    zHelper.logAlert("wxCheckJsApi, success, configuring WeChat");
                    zHelper.log(JSON.stringify(res));
                    // TODO(zzn):
                    // uncomment update it here
                    item.configureWeChat_(that.model_);
                },
                fail: function (res) {
                    zHelper.logAlert("wxCheckJsApi, faile");
                    zHelper.log(JSON.stringify(res));
                }
            });

        });

        zHelper.log("XXX after setting wechat");
        this.panelView_.addChild(item.getDom());
    };

    return {
        Controller: Controller
    };
})($, wx, zHelper);<|endoftext|>


<commit_before>/*
This file contains all of the code needed to create four JSONs corresponding
to four distinct sections in index.html: work, education, projects and a
header with biographical information.

In addition, this file also uses code from helper.js to render index.html
correctly.
 */

/* JSON object containing biographical info */
var bio = {
  'name': 'Vishal Lama',
  'role': 'Web Developer',
  'contacts': {
    'mobile': '123-456-7890',
    'email': 'contact@vishallama.org',
    'github': 'vishallama',
    'twitter': '@vishallama',
    'location': 'Cedar City, UT'
  },
  'welcomeMessage': 'Welcome!',
  'skills': [
    'Python',
    'JavaScript',
    'SML(NJ)',
    'Scala',
    'HTML/CSS',
    'Bootstrap',
    'Linux'
  ],
  'biopic': 'images/vishal.png'
};

bio.display = function() {
  var formattedName = HTMLheaderName.
    replace('%data%', bio.name);
  var formattedRole = HTMLheaderRole.
    replace('%data%', bio.role);

  var formattedMobile = HTMLmobile.
    replace('%data%', bio.contacts.mobile);
  var formattedEmail= HTMLemail.
    replace('%data%', bio.contacts.email);
  var formattedTwitter= HTMLtwitter.
    replace('%data%', bio.contacts.twitter);
  var formattedGithub = HTMLgithub.
    replace('%data%', bio.contacts.github);
  var formattedLocation = HTMLlocation.
    replace('%data%', bio.contacts.location);

  var formattedBioPic = HTMLbioPic.
    replace('%data%', bio.biopic);
  var formattedWelcomeMessage = HTMLwelcomeMsg.
    replace('%data%', bio.welcomeMessage);

  var contactItems = [
    formattedMobile,
    formattedEmail,
    formattedTwitter,
    formattedGithub,
    formattedLocation
  ];

  $('#header').
    prepend(formattedName + formattedRole).
    append(formattedBioPic + formattedWelcomeMessage).
    append(HTMLskillsStart);

  $('#topContacts').prepend(contactItems);
  $('#footerContacts').prepend(contactItems);

  bio.skills.forEach(function (skill) {
    var formattedSkill = HTMLskills.replace('%data%', skill);
    $('#skills').append(formattedSkill);
  });
};

/* JSON object containing work info */
var work = {
  'jobs': [
    {
      'employer': 'Cedar City Yogurt LLC',
      'title': 'Co-owner',
      'location': 'Cedar City, UT',
      'dates': '2014 - 2015',
      'description': 'Ran and managed a family-owned frozen yogurt store.'
    },
    {
      'employer': 'Arabic and Indian Foods LLC',
      'title': 'Co-owner',
      'location': 'Cedar City, UT',
      'dates': '2012 - 2015',
      'description': 'Ran and managed a grocery store.'
    },
    {
      'employer': 'Southern Utah University',
      'title': 'Tutor, Grader and TA',
      'location': 'Cedar City, UT',
      'dates': '2006- 2011',
      'description': 'Tutored, graded HW and performed TA-related tasks' +
      ' for a variety of math and computer science courses, including ' +
      'calculus, probability and statistics, linear algebra, college ' +
      'algebra, introductory logic, and introductory java programming.'
    }
  ]
};

work.display =  function(){
  work.jobs.forEach(function(workEntry) {
    var formattedWorkEmployer = HTMLworkEmployer.
      replace('%data%', workEntry.employer);
    var formattedWorkTitle = HTMLworkTitle.
      replace('%data%', workEntry.title);
    var formattedWorkLocation = HTMLworkLocation.
      replace('%data%', workEntry.location);
    var formattedWorkDates = HTMLworkDates.
      replace('%data%', workEntry.dates);
    var formattedWorkDescription = HTMLworkDescription.
      replace('%data%', workEntry.description);

    $('#workExperience').append(HTMLworkStart);
    $('.work-entry:last').
      append(
      formattedWorkEmployer +
      formattedWorkTitle +
      formattedWorkLocation +
      formattedWorkDates +
      formattedWorkDescription
    );
  });
};

/* JSON object containing info on projects */
var projects = {
  'projects': [
    {
      'title': 'Udacity Front-End Web Developer Nanodegree - Portfolio Site',
      'dates': '2015',
      'description': 'One-page fully-responsive website to display a ' +
      'portfolio of projects. Written using HTML, CSS, jQuery, and Bootstrap.',
      'images': [
        'images/udacity-frontend-portfolio-img01-300x150xs.png',
        'images/udacity-frontend-portfolio-img02-300x150xs.png'
      ]
    },
    {
      'title': 'Udacity Front-End Web Developer Nanodegree - Online Resume',
      'dates': '2015',
      'description': 'One-page responsive website for displaying an ' +
      'interactive online resume. Written using HTML, CSS, JavaScript, and ' +
      'jQuery.',
      'images': [
        'images/udacity-fullstack-movie-trailer-img02-300x150xs.png',
        'images/udacity-fullstack-movie-trailer-img03-300x150xs.png'
      ]
    },
    {
      'title': 'Udacity Full Stack Web Developer Nanodegree - Movie Trailer ' +
      'Website',
      'dates': '2015',
      'description': 'One-page responsive website for displaying movie ' +
      'trailers. Written using HTML, CSS, jQuery, and Bootstrap.',
      'images': [
        'images/udacity-fullstack-movie-trailer-img01-300x150xs.png',
        'images/udacity-fullstack-movie-trailer-img04-300x150xs.png'
      ]
    }
  ]
};

projects.display = function(){
  projects.projects.forEach(function(project) {
    var formattedProjectTitle = HTMLprojectTitle.
      replace('%data%', project.title);
    var formattedProjectDates = HTMLprojectDates.
      replace('%data%', project.dates);
    var formattedProjectDescription = HTMLprojectDescription.
      replace('%data%', project.description);

    $('#projects').append(HTMLprojectStart);
    $('.project-entry:last').append(
      formattedProjectTitle +
      formattedProjectDates +
      formattedProjectDescription
    );

    project.images.forEach(function (imageUrl) {
      var formattedProjectImage = HTMLprojectImage.
        replace('%data%', imageUrl);
      $('.project-entry:last').append(formattedProjectImage);
    });
  });
};

/* JSON object containing education info */
var education = {
  'schools': [
    {
      'name': 'Southern Utah University',
      'location': 'Cedar City, UT',
      'degree': 'BS',
      'majors': ['Math (Pure)'],
      'dates': 2011,
      'url': 'http://www.suu.edu'
      }
  ],
  'onlineCourses': [
    {
      'title': 'Intro to HTML and CSS',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-html-and-css--ud304'
    },
    {
      'title': 'Responsive Web Design Fundamentals',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/responsive-web-design-fundamentals--ud893'
    },
    {
      'title': 'Responsive Images',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/responsive-images--ud882'
    },
    {
      'title': 'JavaScript Basics',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/javascript-basics--ud804'
    },
    {
      'title': 'Linux Command Line Basics',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/linux-command-line-basics--ud595'
    },
    {
      'title': 'How to Use Git and GitHub',
      'school': 'Udacity',
      'date': 2015,
      'url':'https://www.udacity.com/course/how-to-use-git-and-github--ud775'
    },
    {
      'title': 'Programming Foundations with Python',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/programming-foundations-with-python--ud036'
    },
    {
      'title': 'Intro to Relational Databases',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-relational-databases--ud197'
    },
    {
      'title': 'Intro to DevOps',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-devops--ud611'
    },
    {
      'title': 'Configuring Linux Web Servers',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/configuring-linux-web-servers--ud299'
    }
  ]
};

education.display = function () {
  education.schools.forEach(function (school) {
    var formattedSchoolName = HTMLschoolName.
        replace('#', school.url).
        replace('%data%', school.name);
    var formattedSchoolDegree = HTMLschoolDegree.
        replace('%data%', school.degree);
    var formattedSchoolDates = HTMLschoolDates.
        replace('%data%', school.dates);
    var formattedSchoolLocation = HTMLschoolLocation.
        replace('%data%', school.location);

    $('#education').append(HTMLschoolStart);
    $('.education-entry:last').append(
        formattedSchoolName +
        formattedSchoolDegree +
        formattedSchoolDates +
        formattedSchoolLocation
    );

    school.majors.forEach(function (major) {
      var formattedSchoolMajor = HTMLschoolMajor.
        replace('%data%', major);
      $('.education-entry:last').append(formattedSchoolMajor);
    });
  });

  $('#education').append(HTMLonlineClasses);
  education.onlineCourses.forEach(function (onlineCourse) {
    var formattedOnlineTitle = HTMLonlineTitle.
      replace('%data%', onlineCourse.title).
      replace('#', onlineCourse.url);
    var formattedOnlineSchool = HTMLonlineSchool.
      replace('%data%', onlineCourse.school);
    var formattedOnlineDates = HTMLonlineDates.
      replace('%data%', onlineCourse.date);

    $('#education').append(HTMLonlineClassStart);
    $('.education-entry:last').append(
      formattedOnlineTitle +
      formattedOnlineSchool +
      formattedOnlineDates
    );
  });
};

/*
Execute display() from each object to render index.html correctly
 */

/* Bio */
bio.display();

/* Work */
work.display();

/* Projects */
projects.display();

/* Education */
education.display();

/* Append internationalizeButton to the main div */
$('#main').append(internationalizeButton);

/* Add a google map */
$('#map-div').append(googleMap);

<commit_msg>Add some 'fake' university<commit_after>/*
This file contains all of the code needed to create four JSONs corresponding
to four distinct sections in index.html: work, education, projects and a
header with biographical information.

In addition, this file also uses code from helper.js to render index.html
correctly.
 */

/* JSON object containing biographical info */
var bio = {
  'name': 'Vishal Lama',
  'role': 'Web Developer',
  'contacts': {
    'mobile': '123-456-7890',
    'email': 'contact@vishallama.org',
    'github': 'vishallama',
    'twitter': '@vishallama',
    'location': 'Cedar City, UT'
  },
  'welcomeMessage': 'Welcome!',
  'skills': [
    'Python',
    'JavaScript',
    'SML(NJ)',
    'Scala',
    'HTML/CSS',
    'Bootstrap',
    'Linux'
  ],
  'biopic': 'images/vishal.png'
};

bio.display = function() {
  var formattedName = HTMLheaderName.
    replace('%data%', bio.name);
  var formattedRole = HTMLheaderRole.
    replace('%data%', bio.role);

  var formattedMobile = HTMLmobile.
    replace('%data%', bio.contacts.mobile);
  var formattedEmail= HTMLemail.
    replace('%data%', bio.contacts.email);
  var formattedTwitter= HTMLtwitter.
    replace('%data%', bio.contacts.twitter);
  var formattedGithub = HTMLgithub.
    replace('%data%', bio.contacts.github);
  var formattedLocation = HTMLlocation.
    replace('%data%', bio.contacts.location);

  var formattedBioPic = HTMLbioPic.
    replace('%data%', bio.biopic);
  var formattedWelcomeMessage = HTMLwelcomeMsg.
    replace('%data%', bio.welcomeMessage);

  var contactItems = [
    formattedMobile,
    formattedEmail,
    formattedTwitter,
    formattedGithub,
    formattedLocation
  ];

  $('#header').
    prepend(formattedName + formattedRole).
    append(formattedBioPic + formattedWelcomeMessage).
    append(HTMLskillsStart);

  $('#topContacts').prepend(contactItems);
  $('#footerContacts').prepend(contactItems);

  bio.skills.forEach(function (skill) {
    var formattedSkill = HTMLskills.replace('%data%', skill);
    $('#skills').append(formattedSkill);
  });
};

/* JSON object containing work info */
var work = {
  'jobs': [
    {
      'employer': 'Cedar City Yogurt LLC',
      'title': 'Co-owner',
      'location': 'Cedar City, UT',
      'dates': '2014 - 2015',
      'description': 'Ran and managed a family-owned frozen yogurt store.'
    },
    {
      'employer': 'Arabic and Indian Foods LLC',
      'title': 'Co-owner',
      'location': 'Cedar City, UT',
      'dates': '2012 - 2015',
      'description': 'Ran and managed a grocery store.'
    },
    {
      'employer': 'Southern Utah University',
      'title': 'Tutor, Grader and TA',
      'location': 'Cedar City, UT',
      'dates': '2006- 2011',
      'description': 'Tutored, graded HW and performed TA-related tasks' +
      ' for a variety of math and computer science courses, including ' +
      'calculus, probability and statistics, linear algebra, college ' +
      'algebra, introductory logic, and introductory java programming.'
    }
  ]
};

work.display =  function(){
  work.jobs.forEach(function(workEntry) {
    var formattedWorkEmployer = HTMLworkEmployer.
      replace('%data%', workEntry.employer);
    var formattedWorkTitle = HTMLworkTitle.
      replace('%data%', workEntry.title);
    var formattedWorkLocation = HTMLworkLocation.
      replace('%data%', workEntry.location);
    var formattedWorkDates = HTMLworkDates.
      replace('%data%', workEntry.dates);
    var formattedWorkDescription = HTMLworkDescription.
      replace('%data%', workEntry.description);

    $('#workExperience').append(HTMLworkStart);
    $('.work-entry:last').
      append(
      formattedWorkEmployer +
      formattedWorkTitle +
      formattedWorkLocation +
      formattedWorkDates +
      formattedWorkDescription
    );
  });
};

/* JSON object containing info on projects */
var projects = {
  'projects': [
    {
      'title': 'Udacity Front-End Web Developer Nanodegree - Portfolio Site',
      'dates': '2015',
      'description': 'One-page fully-responsive website to display a ' +
      'portfolio of projects. Written using HTML, CSS, jQuery, and Bootstrap.',
      'images': [
        'images/udacity-frontend-portfolio-img01-300x150xs.png',
        'images/udacity-frontend-portfolio-img02-300x150xs.png'
      ]
    },
    {
      'title': 'Udacity Front-End Web Developer Nanodegree - Online Resume',
      'dates': '2015',
      'description': 'One-page responsive website for displaying an ' +
      'interactive online resume. Written using HTML, CSS, JavaScript, and ' +
      'jQuery.',
      'images': [
        'images/udacity-fullstack-movie-trailer-img02-300x150xs.png',
        'images/udacity-fullstack-movie-trailer-img03-300x150xs.png'
      ]
    },
    {
      'title': 'Udacity Full Stack Web Developer Nanodegree - Movie Trailer ' +
      'Website',
      'dates': '2015',
      'description': 'One-page responsive website for displaying movie ' +
      'trailers. Written using HTML, CSS, jQuery, and Bootstrap.',
      'images': [
        'images/udacity-fullstack-movie-trailer-img01-300x150xs.png',
        'images/udacity-fullstack-movie-trailer-img04-300x150xs.png'
      ]
    }
  ]
};

projects.display = function(){
  projects.projects.forEach(function(project) {
    var formattedProjectTitle = HTMLprojectTitle.
      replace('%data%', project.title);
    var formattedProjectDates = HTMLprojectDates.
      replace('%data%', project.dates);
    var formattedProjectDescription = HTMLprojectDescription.
      replace('%data%', project.description);

    $('#projects').append(HTMLprojectStart);
    $('.project-entry:last').append(
      formattedProjectTitle +
      formattedProjectDates +
      formattedProjectDescription
    );

    project.images.forEach(function (imageUrl) {
      var formattedProjectImage = HTMLprojectImage.
        replace('%data%', imageUrl);
      $('.project-entry:last').append(formattedProjectImage);
    });
  });
};

/* JSON object containing education info */
var education = {
  'schools': [
    { 'name': 'Some Cool University',
      'location': 'San Francisco, CA',
      'degree': 'MS',
      'majors': ['Computer Science'],
      'dates': '2011-2013',
      'url': 'http://www.stanford.edu'
    },
    {
      'name': 'Southern Utah University',
      'location': 'Cedar City, UT',
      'degree': 'BS',
      'majors': ['Math (Pure)'],
      'dates': 2011,
      'url': 'http://www.suu.edu'
      }
  ],
  'onlineCourses': [
    {
      'title': 'Intro to HTML and CSS',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-html-and-css--ud304'
    },
    {
      'title': 'Responsive Web Design Fundamentals',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/responsive-web-design-fundamentals--ud893'
    },
    {
      'title': 'Responsive Images',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/responsive-images--ud882'
    },
    {
      'title': 'JavaScript Basics',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/javascript-basics--ud804'
    },
    {
      'title': 'Linux Command Line Basics',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/linux-command-line-basics--ud595'
    },
    {
      'title': 'How to Use Git and GitHub',
      'school': 'Udacity',
      'date': 2015,
      'url':'https://www.udacity.com/course/how-to-use-git-and-github--ud775'
    },
    {
      'title': 'Programming Foundations with Python',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/programming-foundations-with-python--ud036'
    },
    {
      'title': 'Intro to Relational Databases',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-relational-databases--ud197'
    },
    {
      'title': 'Intro to DevOps',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/intro-to-devops--ud611'
    },
    {
      'title': 'Configuring Linux Web Servers',
      'school': 'Udacity',
      'date': 2015,
      'url': 'https://www.udacity.com/course/configuring-linux-web-servers--ud299'
    }
  ]
};

education.display = function () {
  education.schools.forEach(function (school) {
    var formattedSchoolName = HTMLschoolName.
        replace('#', school.url).
        replace('%data%', school.name);
    var formattedSchoolDegree = HTMLschoolDegree.
        replace('%data%', school.degree);
    var formattedSchoolDates = HTMLschoolDates.
        replace('%data%', school.dates);
    var formattedSchoolLocation = HTMLschoolLocation.
        replace('%data%', school.location);

    $('#education').append(HTMLschoolStart);
    $('.education-entry:last').append(
        formattedSchoolName +
        formattedSchoolDegree +
        formattedSchoolDates +
        formattedSchoolLocation
    );

    school.majors.forEach(function (major) {
      var formattedSchoolMajor = HTMLschoolMajor.
        replace('%data%', major);
      $('.education-entry:last').append(formattedSchoolMajor);
    });
  });

  $('#education').append(HTMLonlineClasses);
  education.onlineCourses.forEach(function (onlineCourse) {
    var formattedOnlineTitle = HTMLonlineTitle.
      replace('%data%', onlineCourse.title).
      replace('#', onlineCourse.url);
    var formattedOnlineSchool = HTMLonlineSchool.
      replace('%data%', onlineCourse.school);
    var formattedOnlineDates = HTMLonlineDates.
      replace('%data%', onlineCourse.date);

    $('#education').append(HTMLonlineClassStart);
    $('.education-entry:last').append(
      formattedOnlineTitle +
      formattedOnlineSchool +
      formattedOnlineDates
    );
  });
};

/*
Execute display() from each object to render index.html correctly
 */

/* Bio */
bio.display();

/* Work */
work.display();

/* Projects */
projects.display();

/* Education */
education.display();

/* Append internationalizeButton to the main div */
$('#main').append(internationalizeButton);

/* Add a google map */
$('#map-div').append(googleMap);

<|endoftext|>


<commit_before>// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.
// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.

/*
This is empty on purpose! Your code to build the resume will go here.
 */
//[string].replace([old],[new])
// biography
var bio = {
    "name": "abdulrahman elhaw ",
    "role": "Web developer",
    "contacts": {
        "mobile": "+20-112-3319313",
        "email": "abd.elsayed@hotmail.com",
        "github": "elhaw",
        "twitter": "@aeaue_body2",
        "location": "Egypt",
        "welcomeMessage": "Welcome to my page, hope you enjoy !!",
    },
    "skills": ["HTML", "Linux", "JavaScript", "C programming", "CSS"],
    "bioPic": ["images/fry.jpg"],
    "display": function() {
        var formattedName = HTMLheaderName.replace("%data%", bio.name);
        var formattedRole = HTMLheaderRole.replace("%data%", bio.role);
        var formatedMobile = HTMLmobile.replace("%data%", bio.contacts.mobile);
        var formatedEmail = HTMLemail.replace("%data%", bio.contacts.email);
        var formatedTwitter = HTMLtwitter.replace("%data%", bio.contacts.twitter);
        var formatedGithub = HTMLgithub.replace("%data%", bio.contacts.github);
        var formatedLocation = HTMLlocation.replace("%data%", bio.contacts.location);
        var formatedPicture = HTMLbioPic.replace("%data%", bio.bioPic);
        var formattedMessage = HTMLwelcomeMsg.replace("%data%", bio.contacts.welcomeMessage);

        $("#header").prepend(formattedRole);
        $("#header").prepend(formattedName);
        $("#topContacts").append(formatedMobile);
        $("#topContacts").append(formatedEmail);
        $("#topContacts").append(formatedTwitter);
        $("#topContacts").append(formatedGithub);
        $("#topContacts").append(formatedLocation);
        $("#header").append(formatedPicture);
        $("#header").append(formattedMessage);

        $("#footerContacts").append(formatedMobile);
        $("#footerContacts").append(formatedEmail);
        $("#footerContacts").append(formatedTwitter);
        $("#footerContacts").append(formatedGithub);
        $("#footerContacts").append(formatedLocation);
        //skills
        var formatedSkillsStart = HTMLskillsStart;
        $("#header").append(formatedSkillsStart);
        if (bio.skills.length !== 0) {
            for (var i = 0; i < bio.skills.length; i++) {
                var formatedSkills = HTMLskills.replace("%data%", bio.skills[i]);
                $("#skills").append(formatedSkills);
            }
        }
    }

};
// work
var work = {
    "jobs": [{
            "employer": "IT solutions",
            "title": "Front-end Web developer",
            "location": "Alexandria",
            "dates": "2016-July till present",
            "description": "responsible for implementing visual and interactive"
        },
        {
            "employer": "overcoffesolution",
            "title": "software developer",
            "location": "Canada",
            "dates": "2020-July till present",
            "description": "develop new software tools to automate fabrication "
        }
    ],
    "display": function() {
        for (var job in work.jobs) {

            var formattedworkStart = HTMLworkStart;
            $("#workExperience").append(formattedworkStart);
            var formatedworkEmployer = HTMLworkEmployer.replace("%data%", work.jobs[job].employer);
            var formatedworkTitle = HTMLworkTitle.replace("%data%", work.jobs[job].title);

            $(".work-entry:last").append(formatedworkEmployer + formatedworkTitle);

            var formatedworkDates = HTMLworkDates.replace("%data%", work.jobs[job].dates);
            $(".work-entry:last").append(formatedworkDates);

            var formatedworkLocation = HTMLworkLocation.replace("%data%", work.jobs[job].location);
            $(".work-entry:last").append(formatedworkLocation);

            var formatedworkDescription = HTMLworkDescription.replace("%data%", work.jobs[job].description);
            $(".work-entry:last").append(formatedworkDescription);
        }

    }
};
//education
var education = {
    "school": [{
            "name": "Mansoura University",
            "degree": "Bachelor",
            "location": "Mansoura",
            "major": "computer science",
            "date": "2009-2015",
            "url": "http://www.mans.edu.eg/"
        },
        {
            "name": "Graz University of technology",
            "degree": "Master",
            "location": "Austria",
            "major": "Software develompment",
            "date": "2018-2019",
            "url": "https://www.tugraz.at/home/"
        }
    ],
    "onlinecourses": [{

            "title": "JavaScript",
            "school": "Udacity",
            "date": "2016",
            "url": "www.lynda.com"

        },
        {
            "title": "Linux Foundation",
            "school": "Edx",
            "date": "2016",
            "url": "www.edx.com"
        }
    ],
    "display": function() {
            var formattedschoolStart = HTMLschoolStart;

        for (var i = 0; i < education.school.length; i++) {
            $("#education").append(formattedschoolStart);
            var formattedschoolName = HTMLschoolName.replace("%data%", education.school[i].name);
            var formattedschoolDegree = HTMLschoolDegree.replace("%data%", education.school[i].degree);
            $(".education-entry:last").append(formattedschoolName + formattedschoolDegree);

            var formattedschoolDates = HTMLschoolDates.replace("%data%", education.school[i].date);
            $(".education-entry:last").append(formattedschoolDates);

            var formattedschoolLocation = HTMLschoolLocation.replace("%data%", education.school[i].location);
            $(".education-entry:last").append(formattedschoolLocation);

            var formattedschoolMajor = HTMLschoolMajor.replace("%data%", education.school[i].major);
            $(".education-entry:last").append(formattedschoolMajor);
        }
        //online classes
        var formattedonlineClasses = HTMLonlineClasses;

        $("#education").append(formattedonlineClasses);

        for ( i = 0; i < education.onlinecourses.length; i++) {
            $("#education").append(formattedschoolStart);
            var formattedonlineTitle = HTMLonlineTitle.replace("%data%", education.onlinecourses[i].title);
            var formattedonlineSchool = HTMLonlineSchool.replace("%data%", education.onlinecourses[i].school);
            $(".education-entry:last").append(formattedonlineTitle + formattedonlineSchool);

            var formattedonlineDates = HTMLonlineDates.replace("%data%", education.onlinecourses[i].date);
            $(".education-entry:last").append(formattedonlineDates);

            var formattedonlineURL = HTMLonlineURL.replace("%data%", education.onlinecourses[i].url);
            $(".education-entry:last").append(formattedonlineURL);
        }
    }
};
//projects
var projects = {

    "project": [{

            "title": "website portfolio",
            "date": "march ,30 2017",
            "description": "My first portfolio in front-end nano degree",
            "url": ["images/197x148.gif", "images/197x148.gif"]
        },
        {
            "title": "Onliine resume",
            "date": "march ,30 2017",
            "description": "The second project is online resume",
            "url": ["images/197x148.gif", "images/197x148.gif"]
        }
    ],
    "display": function() {
        for (var i = 0; i < projects.project.length; i++) {

            var formattedprojectStart = HTMLprojectStart;
            $("#projects").append(formattedprojectStart);
            var formattedprojectTitle = HTMLprojectTitle.replace("%data%", projects.project[i].title);
            $(".project-entry:last").append(formattedprojectTitle);

            var formatteprojectDates = HTMLprojectDates.replace("%data%", projects.project[i].date);
            $(".project-entry:last").append(formatteprojectDates);

            var formattedprojectDescription = HTMLprojectDescription.replace("%data%", projects.project[i].description);
            $(".project-entry:last").append(formattedprojectDescription);
            for (var j = 0; j < projects.project[i].url.length; j++) {
                var formattedprojectImage = HTMLprojectImage.replace("%data%", projects.project[i].url[j]);
                $(".project-entry:last").append(formattedprojectImage);
            }

        }
    }
};

bio.display();
work.display();
projects.display();
education.display();

$("#mapDiv").append(googleMap);

// internationalize
function inName(name) {
    var fields = name.split(" ");
    var internationalize = fields[0][0].toLocaleUpperCase() + fields[0].slice(1) + " " + fields[1].toLocaleUpperCase();

    return internationalize;
}
$("#main").append(internationalizeButton);<commit_msg>chnage property name bioPic to biopic<commit_after>// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.
// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.

/*
This is empty on purpose! Your code to build the resume will go here.
 */
//[string].replace([old],[new])
// biography
var bio = {
    "name": "abdulrahman elhaw ",
    "role": "Web developer",
    "contacts": {
        "mobile": "+20-112-3319313",
        "email": "abd.elsayed@hotmail.com",
        "github": "elhaw",
        "twitter": "@aeaue_body2",
        "location": "Egypt",
        "welcomeMessage": "Welcome to my page, hope you enjoy !!",
    },
    "skills": ["HTML", "Linux", "JavaScript", "C programming", "CSS"],
    "biopic": ["images/fry.jpg"],
    "display": function() {
        var formattedName = HTMLheaderName.replace("%data%", bio.name);
        var formattedRole = HTMLheaderRole.replace("%data%", bio.role);
        var formatedMobile = HTMLmobile.replace("%data%", bio.contacts.mobile);
        var formatedEmail = HTMLemail.replace("%data%", bio.contacts.email);
        var formatedTwitter = HTMLtwitter.replace("%data%", bio.contacts.twitter);
        var formatedGithub = HTMLgithub.replace("%data%", bio.contacts.github);
        var formatedLocation = HTMLlocation.replace("%data%", bio.contacts.location);
        var formatedPicture = HTMLbioPic.replace("%data%", bio.biopic);
        var formattedMessage = HTMLwelcomeMsg.replace("%data%", bio.contacts.welcomeMessage);

        $("#header").prepend(formattedRole);
        $("#header").prepend(formattedName);
        $("#topContacts").append(formatedMobile);
        $("#topContacts").append(formatedEmail);
        $("#topContacts").append(formatedTwitter);
        $("#topContacts").append(formatedGithub);
        $("#topContacts").append(formatedLocation);
        $("#header").append(formatedPicture);
        $("#header").append(formattedMessage);

        $("#footerContacts").append(formatedMobile);
        $("#footerContacts").append(formatedEmail);
        $("#footerContacts").append(formatedTwitter);
        $("#footerContacts").append(formatedGithub);
        $("#footerContacts").append(formatedLocation);
        //skills
        var formatedSkillsStart = HTMLskillsStart;
        $("#header").append(formatedSkillsStart);
        if (bio.skills.length !== 0) {
            for (var i = 0; i < bio.skills.length; i++) {
                var formatedSkills = HTMLskills.replace("%data%", bio.skills[i]);
                $("#skills").append(formatedSkills);
            }
        }
    }

};
// work
var work = {
    "jobs": [{
            "employer": "IT solutions",
            "title": "Front-end Web developer",
            "location": "Alexandria",
            "dates": "2016-July till present",
            "description": "responsible for implementing visual and interactive"
        },
        {
            "employer": "overcoffesolution",
            "title": "software developer",
            "location": "Canada",
            "dates": "2020-July till present",
            "description": "develop new software tools to automate fabrication "
        }
    ],
    "display": function() {
        for (var job in work.jobs) {

            var formattedworkStart = HTMLworkStart;
            $("#workExperience").append(formattedworkStart);
            var formatedworkEmployer = HTMLworkEmployer.replace("%data%", work.jobs[job].employer);
            var formatedworkTitle = HTMLworkTitle.replace("%data%", work.jobs[job].title);

            $(".work-entry:last").append(formatedworkEmployer + formatedworkTitle);

            var formatedworkDates = HTMLworkDates.replace("%data%", work.jobs[job].dates);
            $(".work-entry:last").append(formatedworkDates);

            var formatedworkLocation = HTMLworkLocation.replace("%data%", work.jobs[job].location);
            $(".work-entry:last").append(formatedworkLocation);

            var formatedworkDescription = HTMLworkDescription.replace("%data%", work.jobs[job].description);
            $(".work-entry:last").append(formatedworkDescription);
        }

    }
};
//education
var education = {
    "school": [{
            "name": "Mansoura University",
            "degree": "Bachelor",
            "location": "Mansoura",
            "major": "computer science",
            "date": "2009-2015",
            "url": "http://www.mans.edu.eg/"
        },
        {
            "name": "Graz University of technology",
            "degree": "Master",
            "location": "Austria",
            "major": "Software develompment",
            "date": "2018-2019",
            "url": "https://www.tugraz.at/home/"
        }
    ],
    "onlinecourses": [{

            "title": "JavaScript",
            "school": "Udacity",
            "date": "2016",
            "url": "www.lynda.com"

        },
        {
            "title": "Linux Foundation",
            "school": "Edx",
            "date": "2016",
            "url": "www.edx.com"
        }
    ],
    "display": function() {
            var formattedschoolStart = HTMLschoolStart;

        for (var i = 0; i < education.school.length; i++) {
            $("#education").append(formattedschoolStart);
            var formattedschoolName = HTMLschoolName.replace("%data%", education.school[i].name);
            var formattedschoolDegree = HTMLschoolDegree.replace("%data%", education.school[i].degree);
            $(".education-entry:last").append(formattedschoolName + formattedschoolDegree);

            var formattedschoolDates = HTMLschoolDates.replace("%data%", education.school[i].date);
            $(".education-entry:last").append(formattedschoolDates);

            var formattedschoolLocation = HTMLschoolLocation.replace("%data%", education.school[i].location);
            $(".education-entry:last").append(formattedschoolLocation);

            var formattedschoolMajor = HTMLschoolMajor.replace("%data%", education.school[i].major);
            $(".education-entry:last").append(formattedschoolMajor);
        }
        //online classes
        var formattedonlineClasses = HTMLonlineClasses;

        $("#education").append(formattedonlineClasses);

        for ( i = 0; i < education.onlinecourses.length; i++) {
            $("#education").append(formattedschoolStart);
            var formattedonlineTitle = HTMLonlineTitle.replace("%data%", education.onlinecourses[i].title);
            var formattedonlineSchool = HTMLonlineSchool.replace("%data%", education.onlinecourses[i].school);
            $(".education-entry:last").append(formattedonlineTitle + formattedonlineSchool);

            var formattedonlineDates = HTMLonlineDates.replace("%data%", education.onlinecourses[i].date);
            $(".education-entry:last").append(formattedonlineDates);

            var formattedonlineURL = HTMLonlineURL.replace("%data%", education.onlinecourses[i].url);
            $(".education-entry:last").append(formattedonlineURL);
        }
    }
};
//projects
var projects = {

    "project": [{

            "title": "website portfolio",
            "date": "march ,30 2017",
            "description": "My first portfolio in front-end nano degree",
            "url": ["images/197x148.gif", "images/197x148.gif"]
        },
        {
            "title": "Onliine resume",
            "date": "march ,30 2017",
            "description": "The second project is online resume",
            "url": ["images/197x148.gif", "images/197x148.gif"]
        }
    ],
    "display": function() {
        for (var i = 0; i < projects.project.length; i++) {

            var formattedprojectStart = HTMLprojectStart;
            $("#projects").append(formattedprojectStart);
            var formattedprojectTitle = HTMLprojectTitle.replace("%data%", projects.project[i].title);
            $(".project-entry:last").append(formattedprojectTitle);

            var formatteprojectDates = HTMLprojectDates.replace("%data%", projects.project[i].date);
            $(".project-entry:last").append(formatteprojectDates);

            var formattedprojectDescription = HTMLprojectDescription.replace("%data%", projects.project[i].description);
            $(".project-entry:last").append(formattedprojectDescription);
            for (var j = 0; j < projects.project[i].url.length; j++) {
                var formattedprojectImage = HTMLprojectImage.replace("%data%", projects.project[i].url[j]);
                $(".project-entry:last").append(formattedprojectImage);
            }

        }
    }
};

bio.display();
work.display();
projects.display();
education.display();

$("#mapDiv").append(googleMap);

// internationalize
function inName(name) {
    var fields = name.split(" ");
    var internationalize = fields[0][0].toLocaleUpperCase() + fields[0].slice(1) + " " + fields[1].toLocaleUpperCase();

    return internationalize;
}
$("#main").append(internationalizeButton);<|endoftext|>


<commit_before>//player 2 win screen
game.p2win = me.ScreenObject.extend({
	/**
	 *  action to perform on state change
	 */
	onResetEvent: function() {
		me.game.world.addChild(new me.Sprite(0, 0, me.loader.getImage("p2win")),-10);
                document.getElementById("mainmenu").style.visibility = "visible";

                me.game.world.addChild(new (me.Renderable.extend({
                    init: function() {
                this._super(me.Renderable, 'init', [270, 240, 300, 50]);
                this.font = new me.Font("FairydustB", 60, "purple");
                me.input.registerPointerEvent('pointerdown',this,this.newGame.bind(this),true);
            },
            draw: function(renderer) {
                this.font.draw(renderer.getContext(), "Player 2 wins", 20, 130);
            },
            update: function(dt){
                return true;
            },

            newGame: function(){
                me.input.releasePointerEvent('pointerdown', this);
                me.state.change(me.state.MENU);

            }

                })));

	},

	/**
	 *  action to perform when leaving this screen (state change)
	 */
	onDestroyEvent: function() {
		document.getElementById("mainmenu").style.visibility = "hidden";
	}
});
<commit_msg>comments still<commit_after>//player 2 win screen
game.p2win = me.ScreenObject.extend({

	 //  action to perform on state change

	onResetEvent: function() {
		me.game.world.addChild(new me.Sprite(0, 0, me.loader.getImage("p2win")),-10);
                document.getElementById("mainmenu").style.visibility = "visible";

                me.game.world.addChild(new (me.Renderable.extend({
                    init: function() {
                this._super(me.Renderable, 'init', [270, 240, 300, 50]);
                this.font = new me.Font("FairydustB", 60, "purple");
                me.input.registerPointerEvent('pointerdown',this,this.newGame.bind(this),true);
            },
            draw: function(renderer) {
                this.font.draw(renderer.getContext(), "Player 2 wins", 20, 130);
            },
            update: function(dt){
                return true;
            },

            newGame: function(){
                me.input.releasePointerEvent('pointerdown', this);
                me.state.change(me.state.MENU);

            }

                })));

	},

            // action to perform when leaving this screen (state change)

	onDestroyEvent: function() {
		document.getElementById("mainmenu").style.visibility = "hidden";
	}
});
<|endoftext|>


<commit_before>// Copyright 2020, University of Colorado Boulder

import joist from './joist.js';

/**
 * Given an array of all possible screens that a sim can have, select and order them according to the relevant query
 * parameters. This also will create a homeScreen if needed, and specify the initialScreen for startup.
 *
 * Parameters suffixed with "Provided" will be true if the that query parameter was actually in the URL, as opposed to
 * the value of the query parameter being the default.
 *
 * @author Chris Klusendorf (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 *
 * @param {Screen[]} allSimScreens - all of the screens declared by the sim, duck-typed for tests
 * @param {boolean} homeScreenQueryParameter - from phet.chipper.queryParameters.homeScreen
 * @param {boolean} homeScreenQueryParameterProvided
 * @param {number} initialScreenIndex - from phet.chipper.queryParameters.initialScreen
 * @param {boolean} initialScreenQueryParameterProvided
 * @param {number[]} screensQueryParameter - from phet.chipper.queryParameters.screens
 * @param {boolean} screensQueryParameterProvided
 * @param {function( selectedSimScreens ):HomeScreen} createHomeScreen
 * @returns {{homeScreen:HomeScreen|null, initialScreen:Screen, selectedSimScreens:Screen[], screens:Screen[]}} - duck-typed for tests
 * @throws Error if incompatible data is provided
 */
const selectScreens = ( allSimScreens,
                        homeScreenQueryParameter,
                        homeScreenQueryParameterProvided,
                        initialScreenIndex,
                        initialScreenQueryParameterProvided,
                        screensQueryParameter,
                        screensQueryParameterProvided,
                        createHomeScreen ) => {

  if ( allSimScreens.length === 1 ) {

    // Problems related to query parameters throw errors instead of assertions (so they are not stripped out)
    if ( homeScreenQueryParameterProvided && homeScreenQueryParameter ) {
      throw new Error( 'cannot specify homeScreen=true for single-screen sims' );
    }
  }

  // the sim screens for this runtime, accounting for specifying a subset with `?screens`
  let selectedSimScreens;

  // The screens to be included, and their order, may be specified via a query parameter.
  // For documentation, see the schema for phet.chipper.queryParameters.screens in initialize-globals.js.
  // TODO: Use QueryStringMachine to validate instead, see https://github.com/phetsims/joist/issues/599
  if ( screensQueryParameterProvided ) {
    //REVIEW: Shouldn't we just see if the result is the default value of `null`, instead of checking if it was
    //REVIEW: provided? See https://github.com/phetsims/joist/issues/614
    selectedSimScreens = screensQueryParameter.map( userIndex => {
      const screenIndex = userIndex - 1; // screens query parameter is 1-based
      if ( screenIndex < 0 || screenIndex > allSimScreens.length - 1 ) {
        throw new Error( 'invalid screen index: ' + userIndex );
      }
      return allSimScreens[ screenIndex ];
    } );
  }
  else {
    selectedSimScreens = allSimScreens;
  }

  // Specifying ?homeScreen=false creates a simulation with no homescreen, and hence is incompatible with ?initialScreen=0,
  // which specifies to show the home screen. Note that the default value of initialScreen:0 is ignored when there is
  // no home screen.
  if ( initialScreenQueryParameterProvided && initialScreenIndex === 0 && homeScreenQueryParameter === false ) {
    // TODO: Use QueryStringMachine to validate instead, see https://github.com/phetsims/joist/issues/599
    throw new Error( 'cannot specify initialScreen=0 when home screen is disabled with homeScreen=false' );
  }

  // For a single screen simulation (whether the simulation only declares one screen, or whether the user has specified
  // a single screen via ?screens), there is no home screen, and hence ?initialScreen=0 which requests to show the homescreen
  // on startup should fail.
  if ( initialScreenQueryParameterProvided && initialScreenIndex === 0 && selectedSimScreens.length === 1 ) {
    throw new Error( 'cannot specify initialScreen=0 when one screen is specified with screens=n' );
  }

  const screens = selectedSimScreens.slice();

  let homeScreen = null;

  // If a sim has multiple screens and the query parameter homeScreen=false is not provided, add a HomeScreen
  if ( selectedSimScreens.length > 1 && homeScreenQueryParameter ) {
    homeScreen = createHomeScreen( selectedSimScreens );
    screens.unshift( homeScreen );
  }

  // The first screen for the sim, can be the HomeScreen if applicable
  let initialScreen;
  if ( homeScreen && initialScreenIndex === 0 ) {

    // If the home screen is supplied, then it is at index 0, so use the query parameter value directly (because the
    // query parameter is 1-based). If `?initialScreen` is 0 then there is no offset to apply.
    initialScreen = homeScreen;
  }
  else if ( initialScreenIndex === 0 ) {

    // There is no home screen and the initialScreen query parameter was not supplied, so we select the first sim screen.
    initialScreen = selectedSimScreens[ 0 ];
  }
  else {

    // If the home screen is not supplied, then the first sim screen is at index 0, so subtract 1 from the query parameter.
    initialScreen = allSimScreens[ initialScreenIndex - 1 ];
  }

  if ( screens.indexOf( initialScreen ) === -1 ) {
    throw new Error( 'screen not found: ' + initialScreenIndex );
  }

  return {
    homeScreen: homeScreen,
    initialScreen: initialScreen,
    selectedSimScreens: selectedSimScreens,
    screens: screens
  };
};

joist.register( 'selectScreens', selectScreens );
export default selectScreens;<commit_msg>Mark `screens` as public, allow graceful failure for `screens` in selectScreens, remove review comment, see https://github.com/phetsims/joist/issues/599 and https://github.com/phetsims/joist/issues/614<commit_after>// Copyright 2020, University of Colorado Boulder

import joist from './joist.js';

/**
 * Given an array of all possible screens that a sim can have, select and order them according to the relevant query
 * parameters. This also will create a homeScreen if needed, and specify the initialScreen for startup.
 *
 * Parameters suffixed with "Provided" will be true if the that query parameter was actually in the URL, as opposed to
 * the value of the query parameter being the default.
 *
 * @author Chris Klusendorf (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 *
 * @param {Screen[]} allSimScreens - all of the screens declared by the sim, duck-typed for tests
 * @param {boolean} homeScreenQueryParameter - from phet.chipper.queryParameters.homeScreen
 * @param {boolean} homeScreenQueryParameterProvided
 * @param {number} initialScreenIndex - from phet.chipper.queryParameters.initialScreen
 * @param {boolean} initialScreenQueryParameterProvided
 * @param {number[]} screensQueryParameter - from phet.chipper.queryParameters.screens
 * @param {boolean} screensQueryParameterProvided
 * @param {function( selectedSimScreens ):HomeScreen} createHomeScreen
 * @returns {{homeScreen:HomeScreen|null, initialScreen:Screen, selectedSimScreens:Screen[], screens:Screen[]}} - duck-typed for tests
 * @throws Error if incompatible data is provided
 */
const selectScreens = ( allSimScreens,
                        homeScreenQueryParameter,
                        homeScreenQueryParameterProvided,
                        initialScreenIndex,
                        initialScreenQueryParameterProvided,
                        screensQueryParameter,
                        screensQueryParameterProvided,
                        createHomeScreen ) => {

  if ( allSimScreens.length === 1 ) {

    // Problems related to query parameters throw errors instead of assertions (so they are not stripped out)
    if ( homeScreenQueryParameterProvided && homeScreenQueryParameter ) {
      throw new Error( 'cannot specify homeScreen=true for single-screen sims' );
    }
  }

  // the ordered list of sim screens for this runtime
  let selectedSimScreens = [];

  // If a subset of screens was specified with the `screens` query parameter, add them to selectedSimScreens. Otherwise,
  // use all of the available sim screens as the default. Note that if the value of `screens` did not pass validation
  // in QueryStringMachine, it will be reverted to its default value of `null`, so it also needs to be checked for
  // truthiness before attempting to use it. For `screens` documentation, see the schema at
  // phet.chipper.queryParameters.screens in initialize-globals.js.
  if ( screensQueryParameterProvided && screensQueryParameter ) {
    screensQueryParameter.forEach( userIndex => {
      const screenIndex = userIndex - 1; // screens query parameter is 1-based

      // add screen to selectedSimScreens if it's a valid index, otherwise error and revert to defaults
      if ( screenIndex >= 0 && screenIndex < allSimScreens.length ) {
        selectedSimScreens.push( allSimScreens[ screenIndex ] );
      }
      else {
        const errorMessage = `invalid screen index: ${userIndex}`;
        assert && assert( false, errorMessage );

        // fail gracefully when running without ?ea and set selectedSimScreens to default values, see https://github.com/phetsims/joist/issues/599
        QueryStringMachine.addWarning( 'screens', userIndex, null, errorMessage );
        selectedSimScreens = allSimScreens;
      }
    } );
  }
  else {
    selectedSimScreens = allSimScreens;
  }

  // Specifying ?homeScreen=false creates a simulation with no homescreen, and hence is incompatible with ?initialScreen=0,
  // which specifies to show the home screen. Note that the default value of initialScreen:0 is ignored when there is
  // no home screen.
  if ( initialScreenQueryParameterProvided && initialScreenIndex === 0 && homeScreenQueryParameter === false ) {
    // TODO: Use QueryStringMachine to validate instead, see https://github.com/phetsims/joist/issues/599
    throw new Error( 'cannot specify initialScreen=0 when home screen is disabled with homeScreen=false' );
  }

  // For a single screen simulation (whether the simulation only declares one screen, or whether the user has specified
  // a single screen via ?screens), there is no home screen, and hence ?initialScreen=0 which requests to show the homescreen
  // on startup should fail.
  if ( initialScreenQueryParameterProvided && initialScreenIndex === 0 && selectedSimScreens.length === 1 ) {
    throw new Error( 'cannot specify initialScreen=0 when one screen is specified with screens=n' );
  }

  const screens = selectedSimScreens.slice();

  let homeScreen = null;

  // If a sim has multiple screens and the query parameter homeScreen=false is not provided, add a HomeScreen
  if ( selectedSimScreens.length > 1 && homeScreenQueryParameter ) {
    homeScreen = createHomeScreen( selectedSimScreens );
    screens.unshift( homeScreen );
  }

  // The first screen for the sim, can be the HomeScreen if applicable
  let initialScreen;
  if ( homeScreen && initialScreenIndex === 0 ) {

    // If the home screen is supplied, then it is at index 0, so use the query parameter value directly (because the
    // query parameter is 1-based). If `?initialScreen` is 0 then there is no offset to apply.
    initialScreen = homeScreen;
  }
  else if ( initialScreenIndex === 0 ) {

    // There is no home screen and the initialScreen query parameter was not supplied, so we select the first sim screen.
    initialScreen = selectedSimScreens[ 0 ];
  }
  else {

    // If the home screen is not supplied, then the first sim screen is at index 0, so subtract 1 from the query parameter.
    initialScreen = allSimScreens[ initialScreenIndex - 1 ];
  }

  if ( screens.indexOf( initialScreen ) === -1 ) {
    throw new Error( 'screen not found: ' + initialScreenIndex );
  }

  return {
    homeScreen: homeScreen,
    initialScreen: initialScreen,
    selectedSimScreens: selectedSimScreens,
    screens: screens
  };
};

joist.register( 'selectScreens', selectScreens );
export default selectScreens;<|endoftext|>


<commit_before>APS.prototype.onMessage = function(data){
	try {
		data = JSON.parse(data)
	}catch(e){
		//Temporary FIX for malformed JSON with scaped single quotes
		data = data.replace(/\\'/g, "'");
		try {
			data = JSON.parse(data);
		}catch(e){
			e.type = "close";
			this.trigger("dead", [e]);
			return this.transport.close();
		}
	}

	var cmd, args, pipe, check = true;

	for(var i in data){
		if(!data.hasOwnProperty(i)) continue;

		cmd = data[i].raw;
		args = data[i].data;
		pipe = null;

		this.log('>>>> ', cmd , " <<<< ", args);

		switch(cmd){
			case 'LOGIN':
				check = false;

				this.state = this.state == 0 ? 1 : this.state;
				this.session.id = args.sessid;
				this.trigger("login", [args.sessid]);

			break;
			case 'IDENT':
				check = false;

				var user = new APS.cUser(args.user, this);
				this.pipes[user.pubid] = user;

				this.user = user;

				if(this.state == 1)
					this.trigger('ready');

				this.session.save();

			break;
			case 'RESTORED':
				if(this.state == 1){
					check = false;
					return;
				};
				check = true;
				//Session restored completed
				this.state = 1;
				if(this.trigger('restored') !== false)
					this.trigger('ready');

			break;
			case 'CHANNEL':
				pipe = new APS.channel(args.pipe, this);
				this.pipes[pipe.pubid] = pipe;
				this.channels[pipe.name] = pipe;

				var u = args.users;

				if(!!u){
					var user;
					//import users from channel to client if any
					for(var i = 0; i < u.length; i++){
						user = this.pipes[u[i].pubid]
						if(!user){
							this.pipes[u[i].pubid] = new APS.user(u[i], this);
							user = this.pipes[u[i].pubid];
						}

						user.channels[pipe.name] = pipe;
						pipe.users[user.pubid] = user;

						//Add user's own pipe to channels list
						user.channels[user.pubid] = user;
					}
				}

				//Add events from queue
				var chanName = pipe.name.toLowerCase();
				if(typeof this.eQueue[chanName] == "object"){
					var queue = this.eQueue[chanName];
					var ev, fn;
					for(var i in queue){
						if(!queue.hasOwnProperty(i)) continue;
						ev = queue[i][0];
						fn = queue[i][1];

						pipe.on(ev,fn);
					}
				}

				pipe.trigger('joined',[this.user, pipe]);
				this.trigger('newChannel', [pipe]);

			break;
			case "SYNC":
				//Event that synchronizes events accross multiple client instances
				var user = this.user;

				pipe = pipe = this.pipes[args.chanid];

				pipe.trigger(args.event, [args.data, user, pipe]);

			break;
			case "EVENT":
				var user = this.pipes[args.from.pubid];

				if(typeof user == "undefined" && !!args.from){
					//Create user it doesn't exists
					user = client.pipe[args.from.pubid] = new APS.user(args.from)
				}

				pipe = this.pipes[args.pipe.pubid];

				if(pipe.pubid == user.pubid){
					pipe = this.user;
				}

				//Trigger event on target
				pipe.trigger(args.event, [args.data, user, pipe]);

			break;
			case 'JOIN':
				var user = this.pipes[args.user.pubid];
				pipe = this.pipes[args.pipe.pubid];

				if(!user){
					this.pipes[args.user.pubid] = new APS.user(args.user, this);
					user = this.pipes[args.user.pubid];
				}

				//Add user's own pipe to channels list
				user.channels[args.user.pubid] = user;

				//Add user to channel list
				pipe.addUser(user);

				//Update channel
				pipe.update(args.pipe.properties);

				pipe.trigger('join', [user, pipe]);

			break;
			case 'LEFT':
				pipe = this.pipes[args.pipe.pubid];
				var user = this.pipes[args.user.pubid];

				delete pipe.users[args.user.pubid];

				//Update channel
				pipe.update(args.pipe.properties);

				pipe.trigger('left', [user, pipe]);

			break;
			case 'ERR' :
				check = false;
				var info = [args.code, args.value, args];

				switch(args.code){
					case "001":
					case "002":
					case "003":
						clearTimeout(this.poller);
						this.trigger("dead", info);
						break;
					case "004":
					case "250":
						this.state = 0;
						this.session.destroy(true);

						if(this.option.session){
							this.reconnect();
						}
						break;
					default:
						this.check();
				}
				this.trigger("error", info);
				this.trigger("error"+args.code, info);

			break;
			default:
				//trigger custom commands
				var info = new Array();
				for(var i in args){
					if(!args.hasOwnProperty(i)) continue;
					info.push(args[i]);
				}
				this.trigger(cmd, info);
		}
	}

	if(check && this.transport.id == 0 && this.transport.state == 1){
		this.check();
	}
}
<commit_msg>changed cmd variable to raw to better describe their definition<commit_after>APS.prototype.onMessage = function(data){
	try {
		data = JSON.parse(data)
	}catch(e){
		//Temporary FIX for malformed JSON with scaped single quotes
		data = data.replace(/\\'/g, "'");
		try {
			data = JSON.parse(data);
		}catch(e){
			e.type = "close";
			this.trigger("dead", [e]);
			return this.transport.close();
		}
	}

	var raw, args, pipe, check = true;

	for(var i in data){
		if(!data.hasOwnProperty(i)) continue;

		raw = data[i].raw;
		args = data[i].data;
		pipe = null;

		this.log('>>>> ', raw , " <<<< ", args);

		switch(raw){
			case 'LOGIN':
				check = false;

				this.state = this.state == 0 ? 1 : this.state;
				this.session.id = args.sessid;
				this.trigger("login", [args.sessid]);

			break;
			case 'IDENT':
				check = false;

				var user = new APS.cUser(args.user, this);
				this.pipes[user.pubid] = user;

				this.user = user;

				if(this.state == 1)
					this.trigger('ready');

				this.session.save();

			break;
			case 'RESTORED':
				if(this.state == 1){
					check = false;
					return;
				};
				check = true;
				//Session restored completed
				this.state = 1;
				if(this.trigger('restored') !== false)
					this.trigger('ready');

			break;
			case 'CHANNEL':
				pipe = new APS.channel(args.pipe, this);
				this.pipes[pipe.pubid] = pipe;
				this.channels[pipe.name] = pipe;

				var u = args.users;

				if(!!u){
					var user;
					//import users from channel to client if any
					for(var i = 0; i < u.length; i++){
						user = this.pipes[u[i].pubid]
						if(!user){
							this.pipes[u[i].pubid] = new APS.user(u[i], this);
							user = this.pipes[u[i].pubid];
						}

						user.channels[pipe.name] = pipe;
						pipe.users[user.pubid] = user;

						//Add user's own pipe to channels list
						user.channels[user.pubid] = user;
					}
				}

				//Add events from queue
				var chanName = pipe.name.toLowerCase();
				if(typeof this.eQueue[chanName] == "object"){
					var queue = this.eQueue[chanName];
					var ev, fn;
					for(var i in queue){
						if(!queue.hasOwnProperty(i)) continue;
						ev = queue[i][0];
						fn = queue[i][1];

						pipe.on(ev,fn);
					}
				}

				pipe.trigger('joined',[this.user, pipe]);
				this.trigger('newChannel', [pipe]);

			break;
			case "SYNC":
				//Event that synchronizes events accross multiple client instances
				var user = this.user;

				pipe = pipe = this.pipes[args.chanid];

				pipe.trigger(args.event, [args.data, user, pipe]);

			break;
			case "EVENT":
				var user = this.pipes[args.from.pubid];

				if(typeof user == "undefined" && !!args.from){
					//Create user it doesn't exists
					user = client.pipe[args.from.pubid] = new APS.user(args.from)
				}

				pipe = this.pipes[args.pipe.pubid];

				if(pipe.pubid == user.pubid){
					pipe = this.user;
				}

				//Trigger event on target
				pipe.trigger(args.event, [args.data, user, pipe]);

			break;
			case 'JOIN':
				var user = this.pipes[args.user.pubid];
				pipe = this.pipes[args.pipe.pubid];

				if(!user){
					this.pipes[args.user.pubid] = new APS.user(args.user, this);
					user = this.pipes[args.user.pubid];
				}

				//Add user's own pipe to channels list
				user.channels[args.user.pubid] = user;

				//Add user to channel list
				pipe.addUser(user);

				//Update channel
				pipe.update(args.pipe.properties);

				pipe.trigger('join', [user, pipe]);

			break;
			case 'LEFT':
				pipe = this.pipes[args.pipe.pubid];
				var user = this.pipes[args.user.pubid];

				delete pipe.users[args.user.pubid];

				//Update channel
				pipe.update(args.pipe.properties);

				pipe.trigger('left', [user, pipe]);

			break;
			case 'ERR' :
				check = false;
				var info = [args.code, args.value, args];

				switch(args.code){
					case "001":
					case "002":
					case "003":
						clearTimeout(this.poller);
						this.trigger("dead", info);
						break;
					case "004":
					case "250":
						this.state = 0;
						this.session.destroy(true);

						if(this.option.session){
							this.reconnect();
						}
						break;
					default:
						this.check();
				}
				this.trigger("error", info);
				this.trigger("error"+args.code, info);

			break;
			default:
				//trigger custom commands
				var info = new Array();
				for(var i in args){
					if(!args.hasOwnProperty(i)) continue;
					info.push(args[i]);
				}
				this.trigger(raw, info);
		}
	}

	if(check && this.transport.id == 0 && this.transport.state == 1){
		this.check();
	}
}
<|endoftext|>