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

/*
 * This is a JSDoc plugin for all of the BB necessary tags
 *
 * Put this file in <JSDoc dir>\app\plugins\ and it will be used whenever JSDoc is run.
 */

BBTag = {};

BBTag.Support = function(symbolArray) {
    this.init();
    if(symbolArray){
        this.populateBySymbolArray(symbolArray);
    }
};

BBTag.Support.prototype.init = function() {
    this.bb50 = false;
    this.bb60 = false;
    this.bb70 = false;
    this.pb10 = false;
    this.common = false;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.resetSupportAttributes = function() {
    this.supportStrings = [];
    this.supportTag = "";
    this.supportTable = "";
    var tableYes = "Y	";
    var tableNo = " 	";

    if(this.bb50 && this.bb60 && this.bb70){
        this.supportStrings.push("BlackBerry OS 5.0+");
        this.supportTag = "bb5.0|bb6.0|bb7.0";
        this.supportTable = tableYes + "\n" + tableYes + "\n" + tableYes + "\n";
    }else if(!this.bb50 && this.bb60 && this.bb70) {
	this.supportStrings.push("BlackBerry OS 6.0+");
	this.supportTag = "bb6.0|bb7.0";
	this.supportTable = tableNo + "\n" + tableYes + "\n" + tableYes + "\n";
    }else if(this.bb50 && !this.bb60 && !this.bb70){
        this.supportStrings.push("BlackBerry OS 5.0");
        this.supportTag = "bb5.0";
        this.supportTable = tableYes + "\n" + tableNo + "\n" + tableNo + "\n";
    }else if(!this.bb50 && this.bb60 && !this.bb70){
        this.supportStrings.push("BlackBerry OS 6.0");
        this.supportTag = "bb6.0";
        this.supportTable = tableNo + "\n" + tableYes + "\n" + tableNo + "\n";
    }else if(!this.bb50 && !this.bb60 && this.bb70){
	this.supportStrings.push("BlackBerry OS 7.0+");
	this.supportingTag = "bb7.0";
	this.supportTable = tableNo + "\n" + tableNo + "\n" + tableYes + "\n";
    } else {// This last else has no support
        this.supportTable = tableNo + "\n" + tableNo + "\n" + tableNo + "\n";
    }

    if(this.pb10){
        this.supportStrings.push("BlackBerry PlayBook");
        if(this.supportTag.length){
            this.supportTag += "|";
        }
        this.supportTag += "pb1.0";
        this.supportTable += tableYes;
    }else{
        this.supportTable += tableNo;
    }

    if(this.common){
        this.supportTag += "|common";
    }
}

BBTag.Support.prototype.populateByBools = function(bb50, bb60, bb70, pb10) {
    this.bb50 |= bb50;
    this.bb60 |= bb60;
    this.bb70 |= bb70;
    this.pb10 |= pb10;
    this.common |= bb50 && bb60 && bb70 && pb10;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.populateBySymbol = function(symbol) {
    // BlackBerry Support Tags
    if(symbol){
        if(symbol.support){
            this.populateBySupport(symbol.support);
        }else if(symbol.comment){
            var BB50 = symbol.comment.getTag("BB50").length;
            var BB50P = symbol.comment.getTag("BB50+").length;
            var BB60 = symbol.comment.getTag("BB60").length;
            var BB60P = symbol.comment.getTag("BB60+").length;
	    var BB70 = symbol.comment.getTag("BB70").length;
            var BB70P = symbol.comment.getTag("BB70+").length;
            var PB10 = symbol.comment.getTag("PB10").length;
            var PB10P = symbol.comment.getTag("PB10+").length;

            symbol.support = new BBTag.Support();
            symbol.support.populateByBools((BB50 || BB50P),
		(BB50P || BB60P || BB60), (BB50P || BB60P || BB60 || BB70P || BB70),
		(PB10 || PB10P));
            this.populateBySupport(symbol.support);
        }
    }
};

BBTag.Support.prototype.populateByString = function(string) {
    // BlackBerry Support Tags
    if(string){
        var BB50 = string.equals("BB50");
        var BB50P = string.equals("BB50+");
        var BB60 = string.equals("BB60");
        var BB60P = string.equals("BB60+");
	var BB70 = string.equals("BB70");
        var BB70P = string.equals("BB70+");
        var PB10 = string.equals("PB10");
        var PB10P = string.equals("PB10+");

        this.populateByBools((BB50 || BB50P), (BB50P || BB60P || BB60),
		(BB50P || BB60P || BB60 || BB70P || BB70), (PB10 || PB10P));
    }
};

BBTag.Support.prototype.populateBySupport = function(support) {

    this.bb50 |= support.bb50;
    this.bb60 |= support.bb60;
    this.bb70 |= support.bb70;
    this.pb10 |= support.pb10;
    this.common |= support.common;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.populateBySymbolArray = function(symbolArray) {
    for ( var i = 0, l = symbolArray.length; i < l; i++){
        var symbol = symbolArray[i];
        this.populateBySymbol(symbol);
    }
};

BBTag.PlaybookSupport = function(){
    var pbSupport = new BBTag.Support();
    pbSupport.populateByBools(false, false, true);
    return pbSupport;
}

function isaClass($) {
    return ($.is("CONSTRUCTOR") || $.isNamespace) && !($.alias == "_global_")
}

/** Fetch and remove additional { foo } parameters from a string * */
function GetType(src) {
    var type = null;

    if(typeof src != "string")
        throw "src must be a string not " + (typeof src);

    if(src.indexOf('{') >= 0){
        var typeRange = src.balance("{", "}");
        if(typeRange[1] == -1)
            throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: " +
                  src;
        type = src.substring(typeRange[0] + 1, typeRange[1]).trim();
        src = src.substring(typeRange[1] + 1);
    }

    return {type : type, remainder : src};
}

JSDOC.PluginManager.registerPlugin("JSDOC.BBTag", {
    onSymbol : function(symbol) {

        if(symbol.comment){
            // If its a class/namespace
            if(isaClass(symbol)){

                var toc = symbol.comment.getTag("toc");
                if(toc.length){
                    // MUST get the original TOC tag ...WHO KNOWS WHY???
                    for ( var i = 0; i < symbol.comment.tags.length; i++){
                        if(symbol.comment.tags[i].title == "toc"){
                            symbol.toc = symbol.comment.tags[i];
                            break;
                        }
                    }
                }

                var notice = symbol.comment.tags.filter(function($, index){$.itemIndex = index; return $.title=="notice" && $.type});
                if(notice.length){
                    // reparse the .type attribute as jsDocs as modifies characters
                    for ( var i = 0; i < notice.length; i++){
                        var n = notice[i];
                        var parts = GetType(symbol.comment.tagTexts[n.itemIndex]);
                        if(parts && parts.type){
                            n.title = parts.type;
                        }
                        n.desc = parts.remainder;
                    }
                    symbol.notice = notice;
                }

                var constructorTag = symbol.comment.getTag("constructor");
                if(constructorTag.length == 0){
                    symbol.noConstructor = true;
                }

                //FeatureID has an optional type attribute
                //If it is missing then the feature is fully supported
                //If it is present than it will represent the limited support
                var featureID = symbol.comment.getTag("featureID");
                if(featureID.length){
                    symbol.featureID = featureID;
                }

                var permission = symbol.comment.getTag("permission");
                if(permission.length){
                    symbol.permission = permission;
                }

                var betaTag = symbol.comment.getTag("beta");
                if(betaTag.length){
                    symbol.betaTag = betaTag;
                }

                var learnTag = symbol.comment.getTag("learns");
                if(learnTag.length){
                    symbol.learnTag = learnTag;
                }
            }else{ // Its a property or method

                var readOnly = symbol.comment.getTag("readOnly");
                if(readOnly.length){
                    symbol.readOnly = readOnly;
                }

                var uri = symbol.comment.getTag("uri");
                if(uri.length){
                    symbol.uri = uri;
                }

                var squareAccessor = symbol.comment.getTag("squareAccessor");
                if(squareAccessor.length){
                    symbol.squareAccessor = squareAccessor;
                }

                var constructedBy = symbol.comment.getTag("constructedBy");
                if(constructedBy.length){
                    symbol.constructedBy = constructedBy;
                }
            }

            var paramCallbacks = symbol.comment.tags.filter(function($){return $.isCallback && $.title == "param"});
            // Mark all parameters as callback based on their tags
            if(paramCallbacks.length){
                for ( var i = 0; i < paramCallbacks.length; i++){
                    var currentCallback = paramCallbacks[i];
                    // There should only be 1 matching param
                    var matchingParams = symbol.params
                    .filter(function($) {
                        return ($.type == currentCallback.type)
                        && ($.name == currentCallback.name)
                        && ($.desc == currentCallback.desc)
                        && ($.isOptional == currentCallback.isOptional)
                        && ($.defaultValue == currentCallback.defaultValue)
                    });
                    // Mark the param a callback
                    if(matchingParams && matchingParams[0]){
                        matchingParams[0].isCallback = true;
                    }
                }
            }

            var fieldCBs = symbol.comment.tags.filter(function($){return $.isCallback && $.title == "field"});
            // Mark all properties as callback based on their tags
            if(fieldCBs.length){
                symbol.isCallback = true;
                for ( var i = 0; i < fieldCBs; i++){
                    currentCB = fieldCBs[i];
                }
            }
        }
    },

    onDocCommentTags : function(comment) {
        if(comment){
            //The name must be nibbled so we get a name property like a normal param
            // They are marked as callbacks for future processing.
            // We mark the items as fields and set the description accordingly
            var propertyCBTags = comment.tags.filter(function($){return $.title == "propertyCB"});
            if(propertyCBTags.length){
                for ( var i = 0; i < propertyCBTags.length; i++){
                    var currentPropertyCBTag = propertyCBTags[i];
                    currentPropertyCBTag.desc = currentPropertyCBTag.nibbleName(currentPropertyCBTag.desc);
                    currentPropertyCBTag.isCallback = true;
                    var fieldTag = new JSDOC.DocTag("field");
                    fieldTag.isCallback = true;
                    fieldTag.name = currentPropertyCBTag.name;
                    comment.tags.push(fieldTag);
                    comment.tags.push(new JSDOC.DocTag("type " + currentPropertyCBTag.type));
                    comment.tags.push(new JSDOC.DocTag("desc " + currentPropertyCBTag.desc));
                }
            }else if(comment.getTag("squareAccessor").length){
                // Push a function tag because we only support [] functions
                comment.tags.push(new JSDOC.DocTag("function"));
            }
        }
    },

    onDocTag : function(docTag) {
        if(docTag.title){
            // Callbacks pretend to be parameters so that their order is preserved
            // The name must be nibbled so we get a name property like a normal param
            // They are marked as callbacks for future processing.
            if(docTag.title == "callback"){
                docTag.desc = docTag.nibbleName(docTag.desc);
                docTag.title = "param";
                docTag.isCallback = true;
            }else if(docTag.title == "learns"){
                docTag.desc = docTag.nibbleName(docTag.desc);
            } else if(docTag.title == "permission"){
                docTag.desc = docTag.nibbleName(docTag.desc);
            }
        }
    },

    onFinishedParsing : function(symbolSet) {
        if(symbolSet){
            var symbols = symbolSet.toArray();
            var classes = symbols.filter(isaClass);
            // create each of the class pages
            for ( var i = 0, l = classes.length; i < l; i++){
                var symbol = classes[i];
                if(symbol){
                    var symbolSupport = new BBTag.Support();
                    symbolSupport.populateBySymbol(symbol);
                    var children = [].concat(symbol.methods,symbol.properties,symbol.events);
                    var childSupport = new BBTag.Support(children);
                    symbol.support.populateBySupport(childSupport);
                }
            }
        }
    }
});
<commit_msg>updating js templates<commit_after>/*
 * Copyright 2010-2011 Research In Motion Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * This is a JSDoc plugin for all of the BB necessary tags
 *
 * Put this file in <JSDoc dir>\app\plugins\ and it will be used whenever JSDoc is run.
 */

BBTag = {};

BBTag.Support = function(symbolArray) {
    this.init();
    if(symbolArray){
        this.populateBySymbolArray(symbolArray);
    }
};

BBTag.Support.prototype.init = function() {
    this.bb50 = false;
    this.bb60 = false;
    this.bb70 = false;
    this.pb10 = false;
	this.ripple = false;
    this.common = false;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.resetSupportAttributes = function() {
    this.supportStrings = [];
    this.supportTag = "";
    this.supportTable = "";
    var tableYes = "Y	";
    var tableNo = " 	";

    if(this.bb50 && this.bb60 && this.bb70){
        this.supportStrings.push("BlackBerry OS 5.0+");
        this.supportTag = "bb5.0|bb6.0|bb7.0";
        this.supportTable = tableYes + "\n" + tableYes + "\n" + tableYes + "\n";
    }else if(!this.bb50 && this.bb60 && this.bb70) {
	this.supportStrings.push("BlackBerry OS 6.0+");
	this.supportTag = "bb6.0|bb7.0";
	this.supportTable = tableNo + "\n" + tableYes + "\n" + tableYes + "\n";
    }else if(this.bb50 && !this.bb60 && !this.bb70){
        this.supportStrings.push("BlackBerry OS 5.0");
        this.supportTag = "bb5.0";
        this.supportTable = tableYes + "\n" + tableNo + "\n" + tableNo + "\n";
    }else if(!this.bb50 && this.bb60 && !this.bb70){
        this.supportStrings.push("BlackBerry OS 6.0");
        this.supportTag = "bb6.0";
        this.supportTable = tableNo + "\n" + tableYes + "\n" + tableNo + "\n";
    }else if(!this.bb50 && !this.bb60 && this.bb70){
	this.supportStrings.push("BlackBerry OS 7.0+");
	this.supportingTag = "bb7.0";
	this.supportTable = tableNo + "\n" + tableNo + "\n" + tableYes + "\n";
    } else {// This last else has no support
        this.supportTable = tableNo + "\n" + tableNo + "\n" + tableNo + "\n";
    }

    if(this.pb10){
        this.supportStrings.push("BlackBerry PlayBook");
        if(this.supportTag.length){
            this.supportTag += "|";
        }
        this.supportTag += "pb1.0";
        this.supportTable += tableYes;
    }else{
        this.supportTable += tableNo;
    }

	if(this.ripple){
        this.supportStrings.push("Ripple Emulator");
        if(this.supportTag.length){
            this.supportTag += "|";
        }
        this.supportTag += "ripple";
        this.supportTable += tableYes;
    }else{
        this.supportTable += tableNo;
    }

    if(this.common){
        this.supportTag += "|common";
    }
}

BBTag.Support.prototype.populateByBools = function(bb50, bb60, bb70, pb10, ripple) {
    this.bb50 |= bb50;
    this.bb60 |= bb60;
    this.bb70 |= bb70;
    this.pb10 |= pb10;
	this.ripple |= ripple;
    this.common |= bb50 && bb60 && bb70 && pb10;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.populateBySymbol = function(symbol) {
    // BlackBerry Support Tags
    if(symbol){
        if(symbol.support){
            this.populateBySupport(symbol.support);
        }else if(symbol.comment){
            var BB50 = symbol.comment.getTag("BB50").length;
            var BB50P = symbol.comment.getTag("BB50+").length;
            var BB60 = symbol.comment.getTag("BB60").length;
            var BB60P = symbol.comment.getTag("BB60+").length;
	    var BB70 = symbol.comment.getTag("BB70").length;
            var BB70P = symbol.comment.getTag("BB70+").length;
            var PB10 = symbol.comment.getTag("PB10").length;
            var PB10P = symbol.comment.getTag("PB10+").length;
			var RIPPLE = symbol.comment.getTag("RIPPLE").length;

            symbol.support = new BBTag.Support();
            symbol.support.populateByBools((BB50 || BB50P),
		(BB50P || BB60P || BB60), (BB50P || BB60P || BB60 || BB70P || BB70),
		(PB10 || PB10P), RIPPLE);
            this.populateBySupport(symbol.support);
        }
    }
};

BBTag.Support.prototype.populateByString = function(string) {
    // BlackBerry Support Tags
    if(string){
        var BB50 = string.equals("BB50");
        var BB50P = string.equals("BB50+");
        var BB60 = string.equals("BB60");
        var BB60P = string.equals("BB60+");
	var BB70 = string.equals("BB70");
        var BB70P = string.equals("BB70+");
        var PB10 = string.equals("PB10");
        var PB10P = string.equals("PB10+");
		var RIPPLE = string.equals("RIPPLE");

        this.populateByBools((BB50 || BB50P), (BB50P || BB60P || BB60),
		(BB50P || BB60P || BB60 || BB70P || BB70), (PB10 || PB10P), RIPPLE);
    }
};

BBTag.Support.prototype.populateBySupport = function(support) {

    this.bb50 |= support.bb50;
    this.bb60 |= support.bb60;
    this.bb70 |= support.bb70;
    this.pb10 |= support.pb10;
	this.ripple |= support.ripple;
    this.common |= support.common;
    this.resetSupportAttributes();
};

BBTag.Support.prototype.populateBySymbolArray = function(symbolArray) {
    for ( var i = 0, l = symbolArray.length; i < l; i++){
        var symbol = symbolArray[i];
        this.populateBySymbol(symbol);
    }
};

BBTag.PlaybookSupport = function(){
    var pbSupport = new BBTag.Support();
    pbSupport.populateByBools(false, false, true);
    return pbSupport;
}

function isaClass($) {
    return ($.is("CONSTRUCTOR") || $.isNamespace) && !($.alias == "_global_")
}

/** Fetch and remove additional { foo } parameters from a string * */
function GetType(src) {
    var type = null;

    if(typeof src != "string")
        throw "src must be a string not " + (typeof src);

    if(src.indexOf('{') >= 0){
        var typeRange = src.balance("{", "}");
        if(typeRange[1] == -1)
            throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: " +
                  src;
        type = src.substring(typeRange[0] + 1, typeRange[1]).trim();
        src = src.substring(typeRange[1] + 1);
    }

    return {type : type, remainder : src};
}

JSDOC.PluginManager.registerPlugin("JSDOC.BBTag", {
    onSymbol : function(symbol) {

        if(symbol.comment){
            // If its a class/namespace
            if(isaClass(symbol)){

                var toc = symbol.comment.getTag("toc");
                if(toc.length){
                    // MUST get the original TOC tag ...WHO KNOWS WHY???
                    for ( var i = 0; i < symbol.comment.tags.length; i++){
                        if(symbol.comment.tags[i].title == "toc"){
                            symbol.toc = symbol.comment.tags[i];
                            break;
                        }
                    }
                }

                var notice = symbol.comment.tags.filter(function($, index){$.itemIndex = index; return $.title=="notice" && $.type});
                if(notice.length){
                    // reparse the .type attribute as jsDocs as modifies characters
                    for ( var i = 0; i < notice.length; i++){
                        var n = notice[i];
                        var parts = GetType(symbol.comment.tagTexts[n.itemIndex]);
                        if(parts && parts.type){
                            n.title = parts.type;
                        }
                        n.desc = parts.remainder;
                    }
                    symbol.notice = notice;
                }

                var constructorTag = symbol.comment.getTag("constructor");
                if(constructorTag.length == 0){
                    symbol.noConstructor = true;
                }

                //FeatureID has an optional type attribute
                //If it is missing then the feature is fully supported
                //If it is present than it will represent the limited support
                var featureID = symbol.comment.getTag("featureID");
                if(featureID.length){
                    symbol.featureID = featureID;
                }

                var permission = symbol.comment.getTag("permission");
                if(permission.length){
                    symbol.permission = permission;
                }

                var betaTag = symbol.comment.getTag("beta");
                if(betaTag.length){
                    symbol.betaTag = betaTag;
                }

                var learnTag = symbol.comment.getTag("learns");
                if(learnTag.length){
                    symbol.learnTag = learnTag;
                }
            }else{ // Its a property or method

                var readOnly = symbol.comment.getTag("readOnly");
                if(readOnly.length){
                    symbol.readOnly = readOnly;
                }

                var uri = symbol.comment.getTag("uri");
                if(uri.length){
                    symbol.uri = uri;
                }

                var squareAccessor = symbol.comment.getTag("squareAccessor");
                if(squareAccessor.length){
                    symbol.squareAccessor = squareAccessor;
                }

                var constructedBy = symbol.comment.getTag("constructedBy");
                if(constructedBy.length){
                    symbol.constructedBy = constructedBy;
                }
            }

            var paramCallbacks = symbol.comment.tags.filter(function($){return $.isCallback && $.title == "param"});
            // Mark all parameters as callback based on their tags
            if(paramCallbacks.length){
                for ( var i = 0; i < paramCallbacks.length; i++){
                    var currentCallback = paramCallbacks[i];
                    // There should only be 1 matching param
                    var matchingParams = symbol.params
                    .filter(function($) {
                        return ($.type == currentCallback.type)
                        && ($.name == currentCallback.name)
                        && ($.desc == currentCallback.desc)
                        && ($.isOptional == currentCallback.isOptional)
                        && ($.defaultValue == currentCallback.defaultValue)
                    });
                    // Mark the param a callback
                    if(matchingParams && matchingParams[0]){
                        matchingParams[0].isCallback = true;
                    }
                }
            }

            var fieldCBs = symbol.comment.tags.filter(function($){return $.isCallback && $.title == "field"});
            // Mark all properties as callback based on their tags
            if(fieldCBs.length){
                symbol.isCallback = true;
                for ( var i = 0; i < fieldCBs; i++){
                    currentCB = fieldCBs[i];
                }
            }
        }
    },

    onDocCommentTags : function(comment) {
        if(comment){
            //The name must be nibbled so we get a name property like a normal param
            // They are marked as callbacks for future processing.
            // We mark the items as fields and set the description accordingly
            var propertyCBTags = comment.tags.filter(function($){return $.title == "propertyCB"});
            if(propertyCBTags.length){
                for ( var i = 0; i < propertyCBTags.length; i++){
                    var currentPropertyCBTag = propertyCBTags[i];
                    currentPropertyCBTag.desc = currentPropertyCBTag.nibbleName(currentPropertyCBTag.desc);
                    currentPropertyCBTag.isCallback = true;
                    var fieldTag = new JSDOC.DocTag("field");
                    fieldTag.isCallback = true;
                    fieldTag.name = currentPropertyCBTag.name;
                    comment.tags.push(fieldTag);
                    comment.tags.push(new JSDOC.DocTag("type " + currentPropertyCBTag.type));
                    comment.tags.push(new JSDOC.DocTag("desc " + currentPropertyCBTag.desc));
                }
            }else if(comment.getTag("squareAccessor").length){
                // Push a function tag because we only support [] functions
                comment.tags.push(new JSDOC.DocTag("function"));
            }
        }
    },

    onDocTag : function(docTag) {
        if(docTag.title){
            // Callbacks pretend to be parameters so that their order is preserved
            // The name must be nibbled so we get a name property like a normal param
            // They are marked as callbacks for future processing.
            if(docTag.title == "callback"){
                docTag.desc = docTag.nibbleName(docTag.desc);
                docTag.title = "param";
                docTag.isCallback = true;
            }else if(docTag.title == "learns"){
                docTag.desc = docTag.nibbleName(docTag.desc);
            } else if(docTag.title == "permission"){
                docTag.desc = docTag.nibbleName(docTag.desc);
            }
        }
    },

    onFinishedParsing : function(symbolSet) {
        if(symbolSet){
            var symbols = symbolSet.toArray();
            var classes = symbols.filter(isaClass);
            // create each of the class pages
            for ( var i = 0, l = classes.length; i < l; i++){
                var symbol = classes[i];
                if(symbol){
                    var symbolSupport = new BBTag.Support();
                    symbolSupport.populateBySymbol(symbol);
                    var children = [].concat(symbol.methods,symbol.properties,symbol.events);
                    var childSupport = new BBTag.Support(children);
                    symbol.support.populateBySupport(childSupport);
                }
            }
        }
    }
});
<|endoftext|>


<commit_before>// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.

import { createConsumer } from "@rails/actioncable";

export default createConsumer();
<commit_msg>Update<commit_after>// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.

import { createConsumer } from "@rails/actioncable";

export default createConsumer();
<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

// opts - parent, list, doc, email
frappe.views.CommunicationList = Class.extend({
	init: function(opts) {
		this.comm_list = [];
		$.extend(this, opts);

		if(this.doc.__islocal) {
			$(this.parent).empty();
			return;
		}

		if(!this.list)
			this.list = frappe.model.get("Communication", {"parenttype": this.doc.doctype, "parent": this.doc.name});

		var sortfn = function (a, b) { return (b.creation > a.creation) ? 1 : -1; }
		this.list = this.list.sort(sortfn);

		this.make();
	},
	make: function() {
		var me = this;
		this.make_body();

		if(this.list && this.list.length) {
			$.each(this.list, function(i, d) {
				me.prepare(d);
				me.make_line(d);
			});
			// show first
			this.comm_list[0].find('.comm-content').toggle(true);
		} else {
			this.clear_list()
		}
	},
	clear_list: function() {
		this.body.remove();
		$("
" + frappe._("No Communication tagged with this ")
			+ this.doc.doctype +" yet.
").appendTo(this.wrapper);
	},
	make_body: function() {
		$(this.parent)
			.empty()

		this.wrapper = $("
\

\
				<button class='btn btn-default' \
					onclick='cur_frm.communication_view.add_reply()'>\
				 "+frappe._("Add Message")+"</button>
\

")
			.appendTo(this.parent);

		this.body = $('
')
		.css({"border":"1px solid #dddddd", "border-radius":"4px"})
			.appendTo(this.wrapper);
	},

	add_reply: function() {
		var subject = this.doc.subject;
		if(!subject && this.list.length) {
			// get subject from previous message
			subject = this.list[0].subject || "[No Subject]";
			if(strip(subject.toLowerCase().split(":")[0])!="re") {
				subject = "Re: " + subject;
			}
		}
		new frappe.views.CommunicationComposer({
			doc: this.doc,
			subject: subject,
			recipients: this.recipients
		})
	},

	prepare: function(doc) {
		//doc.when = comment_when(this.doc.modified);
		doc.when = doc.creation;
		if(!doc.content) doc.content = "[no content]";
		if(!frappe.utils.is_html(doc.content)) {
			doc.content = doc.content.replace(/\n/g, "
");
		}
		doc.content = frappe.utils.remove_script_and_style(doc.content);

		if(!doc.sender) doc.sender = "[unknown sender]";
		doc._sender = doc.sender.replace(/</, "<").replace(/>/, ">");
		doc.content = doc.content.split("-----"+frappe._("In response to")+"-----")[0];
		doc.content = doc.content.split("-----"+frappe._("Original Message")+"-----")[0];
	},

	make_line: function(doc) {
		var me = this;
		doc.icon = {
			"Email": "icon-envelope",
			"Chat": "icon-comments",
			"Phone": "icon-phone",
			"SMS": "icon-mobile-phone",
		}[doc.communication_medium] || "icon-envelope";
		var comm = $(repl('
\

\

 %(_sender)s
\

%(subject)s
\

%(when)s
\

\

\

\

\

\
						'+frappe._('Show Details')+'\

\

\

', doc))
			.appendTo(this.body);

		if(!doc.name) {
			comm.find(".show-details").toggle(false);
		}

		comm.find(".comm-header")
			.css({"cursor":"pointer"})
			.click(function() {
				$(this).parent().find(".comm-content").toggle();
			});

		this.comm_list.push(comm);
		comm.find(".comm-content .inner").html(doc.content);
	}
});

frappe.views.CommunicationComposer = Class.extend({
	init: function(opts) {
		$.extend(this, opts)
		this.make();
		this.dialog.show();
	},
	make: function() {
		var me = this;
		this.dialog = new frappe.ui.Dialog({
			title: frappe._("Add Reply") + ": " + (this.subject || ""),
			no_submit_on_enter: true,
			fields: [
				{label:frappe._("To"), fieldtype:"Data", reqd: 1, fieldname:"recipients",
					description:frappe._("Email addresses, separted by commas")},
				{label:frappe._("Subject"), fieldtype:"Data", reqd: 1,
					fieldname:"subject"},
				{label:frappe._("Message"), fieldtype:"Text Editor", reqd: 1,
					fieldname:"content"},
				{label:frappe._("Send As Email"), fieldtype:"Check",
					fieldname:"send_email"},
				{label:frappe._("Communication Medium"), fieldtype:"Select",
					options: ["Phone", "Chat", "Email", "SMS", "Other"],
					fieldname:"communication_medium"},
				{label:frappe._("Sent or Received"), fieldtype:"Select",
					options: ["Received", "Sent"],
					fieldname:"sent_or_received"},
				{label:frappe._("Send"), fieldtype:"Button",
					fieldname:"send"},
				{label:frappe._("Send Me A Copy"), fieldtype:"Check",
					fieldname:"send_me_a_copy"},
				{label:frappe._("Attach Document Print"), fieldtype:"Check",
					fieldname:"attach_document_print"},
				{label:frappe._("Select Print Format"), fieldtype:"Select",
					fieldname:"select_print_format"},
				{label:frappe._("Select Attachments"), fieldtype:"HTML",
					fieldname:"select_attachments"}
			]
		});

		this.dialog.$wrapper.find("[data-edit='outdent']").remove();
		this.dialog.get_input("send").addClass("btn-primary");

		$(document).on("upload_complete", function(event, filename, fileurl) {
			if(me.dialog.display) {
				var wrapper = $(me.dialog.fields_dict.select_attachments.wrapper);

				// find already checked items
				var checked_items = wrapper.find('[data-file-name]:checked').map(function() {
					return $(this).attr("data-file-name");
				});

				// reset attachment list
				me.setup_attach();

				// check latest added
				checked_items.push(filename);

				$.each(checked_items, function(i, filename) {
					wrapper.find('[data-file-name="'+ filename +'"]').prop("checked", true);
				});
			}
		})
		this.prepare();
	},
	prepare: function() {
		this.setup_print();
		this.setup_attach();
		this.setup_email();
		this.setup_autosuggest();
		$(this.dialog.fields_dict.recipients.input).val(this.recipients || "").change();
		$(this.dialog.fields_dict.subject.input).val(this.subject || "").change();
		this.setup_earlier_reply();
	},
	setup_print: function() {
		// print formats
		var fields = this.dialog.fields_dict;

		// toggle print format
		$(fields.attach_document_print.input).click(function() {
			$(fields.select_print_format.wrapper).toggle($(this).prop("checked"));
		});

		// select print format
		$(fields.select_print_format.wrapper).toggle(false);
		$(fields.select_print_format.input)
			.empty()
			.add_options(cur_frm.print_formats)
			.val(cur_frm.print_formats[0]);

	},
	setup_attach: function() {
		var fields = this.dialog.fields_dict;
		var attach = $(fields.select_attachments.wrapper);

		var files = cur_frm.get_files();
		if(files.length) {
			$("
"+frappe._("Add Attachments")+":
").appendTo(attach.empty());
			$.each(files, function(i, f) {
				$(repl("
<input type='checkbox' \
					data-file-name='%(file)s'> %(file)s
", {file:f})).appendTo(attach)
			});
		}
	},
	setup_email: function() {
		// email
		var me = this;
		var fields = this.dialog.fields_dict;

		if(this.attach_document_print) {
			$(fields.send_me_a_copy.input).click();
			$(fields.attach_document_print.input).click();
			$(fields.select_print_format.wrapper).toggle(true);
		}

		$(fields.send_email.input).prop("checked", true)

		// toggle print format
		$(fields.send_email.input).click(function() {
			$(fields.communication_medium.wrapper).toggle(!!!$(this).prop("checked"));
			$(fields.sent_or_received.wrapper).toggle(!!!$(this).prop("checked"));
			$(fields.send.input).html($(this).prop("checked") ? "Send" : "Add Communication");
		});

		// select print format
		$(fields.communication_medium.wrapper).toggle(false);
		$(fields.sent_or_received.wrapper).toggle(false);

		$(fields.send.input).click(function() {
			var btn = this;
			var form_values = me.dialog.get_values();
			if(!form_values) return;

			var selected_attachments = $.map($(me.dialog.wrapper)
				.find("[data-file-name]:checked"), function(element) {
					return $(element).attr("data-file-name");
				})

			if(form_values.attach_document_print) {
				_p.build(form_values.select_print_format || "", function(print_format_html) {
					me.send_email(btn, form_values, selected_attachments, print_format_html);
				});
			} else {
				me.send_email(btn, form_values, selected_attachments);
			}
		});
	},

	send_email: function(btn, form_values, selected_attachments, print_html) {
		var me = this;

		if(!form_values.attach_document_print) {
			print_html = "";
		}

		if(form_values.send_email) {
			if(cur_frm && !frappe.model.can_email(me.doc.doctype, cur_frm)) {
				msgprint(frappe._("You are not allowed to send emails related to this document."));
				return;
			}

			form_values.communication_medium = "Email";
			form_values.sent_or_received = "Sent";
		};

		return frappe.call({
			method:"frappe.core.doctype.communication.communication.make",
			args: {
				sender: [frappe.user_info(user).fullname, frappe.boot.user.email],
				recipients: form_values.recipients,
				subject: form_values.subject,
				content: form_values.content,
				doctype: me.doc.doctype,
				name: me.doc.name,
				send_me_a_copy: form_values.send_me_a_copy,
				send_email: form_values.send_email,
				print_html: print_html,
				communication_medium: form_values.communication_medium,
				sent_or_received: form_values.sent_or_received,
				attachments: selected_attachments
			},
			btn: btn,
			callback: function(r) {
				if(!r.exc) {
					if(form_values.send_email)
						msgprint("Email sent to " + form_values.recipients);
					me.dialog.hide();
					cur_frm.reload_doc();
				} else {
					msgprint("There were errors while sending email. Please try again.")
				}
			}
		});
	},

	setup_earlier_reply: function() {
		var fields = this.dialog.fields_dict;
		var comm_list = cur_frm.communication_view
			? cur_frm.communication_view.list
			: [];
		var signature = frappe.boot.user.email_signature || "";

		if(!frappe.utils.is_html(signature)) {
			signature = signature.replace(/\n/g, "
");
		}

		if(this.real_name) {
			this.message = '
'+frappe._('Dear') +' ' + this.real_name + ",
" + (this.message || "");
		}

		var reply = (this.message || "")
			+ "

"	+ signature;

		if(comm_list.length > 0) {
			fields.content.set_input(reply
				+ "

"
				+"-----"+frappe._("In response to")+"-----

"
				+ comm_list[0].content);
		} else {
			fields.content.set_input(reply);
		}
	},
	setup_autosuggest: function() {
		var me = this;

		function split( val ) {
			return val.split( /,\s*/ );
		}
		function extractLast( term ) {
			return split(term).pop();
		}

		$(this.dialog.fields_dict.recipients.input)
			.bind( "keydown", function(event) {
				if (event.keyCode === $.ui.keyCode.TAB &&
						$(this).data( "autocomplete" ).menu.active ) {
					event.preventDefault();
				}
			})
			.autocomplete({
				source: function(request, response) {
					return frappe.call({
						method:'frappe.utils.email_lib.get_contact_list',
						args: {
							'select': "email_id",
							'from': "Contact",
							'where': "email_id",
							'txt': extractLast(request.term).value || '%'
						},
						callback: function(r) {
							response($.ui.autocomplete.filter(
								r.cl || [], extractLast(request.term)));
						}
					});
				},
				appendTo: this.dialog.$wrapper,
				focus: function() {
					// prevent value inserted on focus
					return false;
				},
				select: function( event, ui ) {
					var terms = split( this.value );
					// remove the current input
					terms.pop();
					// add the selected item
					terms.push( ui.item.value );
					// add placeholder to get the comma-and-space at the end
					terms.push( "" );
					this.value = terms.join( ", " );
					return false;
				}
			});
	}
});

<commit_msg>communication medium added in dialog view<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

// opts - parent, list, doc, email
frappe.views.CommunicationList = Class.extend({
	init: function(opts) {
		this.comm_list = [];
		$.extend(this, opts);

		if(this.doc.__islocal) {
			$(this.parent).empty();
			return;
		}

		if(!this.list)
			this.list = frappe.model.get("Communication", {"parenttype": this.doc.doctype, "parent": this.doc.name});

		var sortfn = function (a, b) { return (b.creation > a.creation) ? 1 : -1; }
		this.list = this.list.sort(sortfn);

		this.make();
	},
	make: function() {
		var me = this;
		this.make_body();

		if(this.list && this.list.length) {
			$.each(this.list, function(i, d) {
				me.prepare(d);
				me.make_line(d);
			});
			// show first
			this.comm_list[0].find('.comm-content').toggle(true);
		} else {
			this.clear_list()
		}
	},
	clear_list: function() {
		this.body.remove();
		$("
" + frappe._("No Communication tagged with this ")
			+ this.doc.doctype +" yet.
").appendTo(this.wrapper);
	},
	make_body: function() {
		$(this.parent)
			.empty()

		this.wrapper = $("
\

\
				<button class='btn btn-default' \
					onclick='cur_frm.communication_view.add_reply()'>\
				 "+frappe._("Add Message")+"</button>
\

")
			.appendTo(this.parent);

		this.body = $('
')
		.css({"border":"1px solid #dddddd", "border-radius":"4px"})
			.appendTo(this.wrapper);
	},

	add_reply: function() {
		var subject = this.doc.subject;
		if(!subject && this.list.length) {
			// get subject from previous message
			subject = this.list[0].subject || "[No Subject]";
			if(strip(subject.toLowerCase().split(":")[0])!="re") {
				subject = "Re: " + subject;
			}
		}
		new frappe.views.CommunicationComposer({
			doc: this.doc,
			subject: subject,
			recipients: this.recipients
		})
	},

	prepare: function(doc) {
		//doc.when = comment_when(this.doc.modified);
		doc.when = doc.creation;
		if(!doc.content) doc.content = "[no content]";
		if(!frappe.utils.is_html(doc.content)) {
			doc.content = doc.content.replace(/\n/g, "
");
		}
		doc.content = frappe.utils.remove_script_and_style(doc.content);

		if(!doc.sender) doc.sender = "[unknown sender]";
		doc._sender = doc.sender.replace(/</, "<").replace(/>/, ">");
		doc.content = doc.content.split("-----"+frappe._("In response to")+"-----")[0];
		doc.content = doc.content.split("-----"+frappe._("Original Message")+"-----")[0];
	},

	make_line: function(doc) {
		var me = this;
		doc.icon = {
			"Email": "icon-envelope",
			"Chat": "icon-comments",
			"Phone": "icon-phone",
			"SMS": "icon-mobile-phone",
		}[doc.communication_medium] || "icon-envelope";
		var comm = $(repl('
\

\

 %(_sender)s
\

%(subject)s
\

%(when)s
\

\

\

\

\

\
						'+frappe._('Show Details')+'\

\

\

', doc))
			.appendTo(this.body);

		if(!doc.name) {
			comm.find(".show-details").toggle(false);
		}

		comm.find(".comm-header")
			.css({"cursor":"pointer"})
			.click(function() {
				$(this).parent().find(".comm-content").toggle();
			});

		this.comm_list.push(comm);
		comm.find(".comm-content .inner").html(doc.content);
	}
});

frappe.views.CommunicationComposer = Class.extend({
	init: function(opts) {
		$.extend(this, opts)
		this.make();
		this.dialog.show();
	},
	make: function() {
		var me = this;
		this.dialog = new frappe.ui.Dialog({
			title: frappe._("Add Reply") + ": " + (this.subject || ""),
			no_submit_on_enter: true,
			fields: [
				{label:frappe._("To"), fieldtype:"Data", reqd: 1, fieldname:"recipients",
					description:frappe._("Email addresses, separted by commas")},
				{label:frappe._("Subject"), fieldtype:"Data", reqd: 1,
					fieldname:"subject"},
				{label:frappe._("Message"), fieldtype:"Text Editor", reqd: 1,
					fieldname:"content"},
				{label:frappe._("Send As Email"), fieldtype:"Check",
					fieldname:"send_email"},
				{label:frappe._("Communication Medium"), fieldtype:"Select",
					options: ["Phone", "Chat", "Email", "SMS", "Visit", "Other"],
					fieldname:"communication_medium"},
				{label:frappe._("Sent or Received"), fieldtype:"Select",
					options: ["Received", "Sent"],
					fieldname:"sent_or_received"},
				{label:frappe._("Send"), fieldtype:"Button",
					fieldname:"send"},
				{label:frappe._("Send Me A Copy"), fieldtype:"Check",
					fieldname:"send_me_a_copy"},
				{label:frappe._("Attach Document Print"), fieldtype:"Check",
					fieldname:"attach_document_print"},
				{label:frappe._("Select Print Format"), fieldtype:"Select",
					fieldname:"select_print_format"},
				{label:frappe._("Select Attachments"), fieldtype:"HTML",
					fieldname:"select_attachments"}
			]
		});

		this.dialog.$wrapper.find("[data-edit='outdent']").remove();
		this.dialog.get_input("send").addClass("btn-primary");

		$(document).on("upload_complete", function(event, filename, fileurl) {
			if(me.dialog.display) {
				var wrapper = $(me.dialog.fields_dict.select_attachments.wrapper);

				// find already checked items
				var checked_items = wrapper.find('[data-file-name]:checked').map(function() {
					return $(this).attr("data-file-name");
				});

				// reset attachment list
				me.setup_attach();

				// check latest added
				checked_items.push(filename);

				$.each(checked_items, function(i, filename) {
					wrapper.find('[data-file-name="'+ filename +'"]').prop("checked", true);
				});
			}
		})
		this.prepare();
	},
	prepare: function() {
		this.setup_print();
		this.setup_attach();
		this.setup_email();
		this.setup_autosuggest();
		$(this.dialog.fields_dict.recipients.input).val(this.recipients || "").change();
		$(this.dialog.fields_dict.subject.input).val(this.subject || "").change();
		this.setup_earlier_reply();
	},
	setup_print: function() {
		// print formats
		var fields = this.dialog.fields_dict;

		// toggle print format
		$(fields.attach_document_print.input).click(function() {
			$(fields.select_print_format.wrapper).toggle($(this).prop("checked"));
		});

		// select print format
		$(fields.select_print_format.wrapper).toggle(false);
		$(fields.select_print_format.input)
			.empty()
			.add_options(cur_frm.print_formats)
			.val(cur_frm.print_formats[0]);

	},
	setup_attach: function() {
		var fields = this.dialog.fields_dict;
		var attach = $(fields.select_attachments.wrapper);

		var files = cur_frm.get_files();
		if(files.length) {
			$("
"+frappe._("Add Attachments")+":
").appendTo(attach.empty());
			$.each(files, function(i, f) {
				$(repl("
<input type='checkbox' \
					data-file-name='%(file)s'> %(file)s
", {file:f})).appendTo(attach)
			});
		}
	},
	setup_email: function() {
		// email
		var me = this;
		var fields = this.dialog.fields_dict;

		if(this.attach_document_print) {
			$(fields.send_me_a_copy.input).click();
			$(fields.attach_document_print.input).click();
			$(fields.select_print_format.wrapper).toggle(true);
		}

		$(fields.send_email.input).prop("checked", true)

		// toggle print format
		$(fields.send_email.input).click(function() {
			$(fields.communication_medium.wrapper).toggle(!!!$(this).prop("checked"));
			$(fields.sent_or_received.wrapper).toggle(!!!$(this).prop("checked"));
			$(fields.send.input).html($(this).prop("checked") ? "Send" : "Add Communication");
		});

		// select print format
		$(fields.communication_medium.wrapper).toggle(false);
		$(fields.sent_or_received.wrapper).toggle(false);

		$(fields.send.input).click(function() {
			var btn = this;
			var form_values = me.dialog.get_values();
			if(!form_values) return;

			var selected_attachments = $.map($(me.dialog.wrapper)
				.find("[data-file-name]:checked"), function(element) {
					return $(element).attr("data-file-name");
				})

			if(form_values.attach_document_print) {
				_p.build(form_values.select_print_format || "", function(print_format_html) {
					me.send_email(btn, form_values, selected_attachments, print_format_html);
				});
			} else {
				me.send_email(btn, form_values, selected_attachments);
			}
		});
	},

	send_email: function(btn, form_values, selected_attachments, print_html) {
		var me = this;

		if(!form_values.attach_document_print) {
			print_html = "";
		}

		if(form_values.send_email) {
			if(cur_frm && !frappe.model.can_email(me.doc.doctype, cur_frm)) {
				msgprint(frappe._("You are not allowed to send emails related to this document."));
				return;
			}

			form_values.communication_medium = "Email";
			form_values.sent_or_received = "Sent";
		};

		return frappe.call({
			method:"frappe.core.doctype.communication.communication.make",
			args: {
				sender: [frappe.user_info(user).fullname, frappe.boot.user.email],
				recipients: form_values.recipients,
				subject: form_values.subject,
				content: form_values.content,
				doctype: me.doc.doctype,
				name: me.doc.name,
				send_me_a_copy: form_values.send_me_a_copy,
				send_email: form_values.send_email,
				print_html: print_html,
				communication_medium: form_values.communication_medium,
				sent_or_received: form_values.sent_or_received,
				attachments: selected_attachments
			},
			btn: btn,
			callback: function(r) {
				if(!r.exc) {
					if(form_values.send_email)
						msgprint("Email sent to " + form_values.recipients);
					me.dialog.hide();
					cur_frm.reload_doc();
				} else {
					msgprint("There were errors while sending email. Please try again.")
				}
			}
		});
	},

	setup_earlier_reply: function() {
		var fields = this.dialog.fields_dict;
		var comm_list = cur_frm.communication_view
			? cur_frm.communication_view.list
			: [];
		var signature = frappe.boot.user.email_signature || "";

		if(!frappe.utils.is_html(signature)) {
			signature = signature.replace(/\n/g, "
");
		}

		if(this.real_name) {
			this.message = '
'+frappe._('Dear') +' ' + this.real_name + ",
" + (this.message || "");
		}

		var reply = (this.message || "")
			+ "

"	+ signature;

		if(comm_list.length > 0) {
			fields.content.set_input(reply
				+ "

"
				+"-----"+frappe._("In response to")+"-----

"
				+ comm_list[0].content);
		} else {
			fields.content.set_input(reply);
		}
	},
	setup_autosuggest: function() {
		var me = this;

		function split( val ) {
			return val.split( /,\s*/ );
		}
		function extractLast( term ) {
			return split(term).pop();
		}

		$(this.dialog.fields_dict.recipients.input)
			.bind( "keydown", function(event) {
				if (event.keyCode === $.ui.keyCode.TAB &&
						$(this).data( "autocomplete" ).menu.active ) {
					event.preventDefault();
				}
			})
			.autocomplete({
				source: function(request, response) {
					return frappe.call({
						method:'frappe.utils.email_lib.get_contact_list',
						args: {
							'select': "email_id",
							'from': "Contact",
							'where': "email_id",
							'txt': extractLast(request.term).value || '%'
						},
						callback: function(r) {
							response($.ui.autocomplete.filter(
								r.cl || [], extractLast(request.term)));
						}
					});
				},
				appendTo: this.dialog.$wrapper,
				focus: function() {
					// prevent value inserted on focus
					return false;
				},
				select: function( event, ui ) {
					var terms = split( this.value );
					// remove the current input
					terms.pop();
					// add the selected item
					terms.push( ui.item.value );
					// add placeholder to get the comma-and-space at the end
					terms.push( "" );
					this.value = terms.join( ", " );
					return false;
				}
			});
	}
});

<|endoftext|>


<commit_before>const randomString = require('randomstring');

const manufacturerNames = ['DJX', 'Parakeet', 'Gruff', 'Unique', 'FlyHawk'];
const modelNames = ['CargoMate', 'Postman', 'ShipIt', 'Air Ship'];

const randomDavAddress = () => {
  return '0x'+randomString.generate({
    length: 40,
    charset: 'hex'
  });
};

/**
 * Returns a random manufacturer name chosen from an array of possible names
 * @return {String} A string representing the name of a manufacturer
 */
const randomManufacturerName = () => {
  return manufacturerNames[Math.floor(Math.random()*manufacturerNames.length)];
};

const randomModelName = () => {
  return modelNames[Math.floor(Math.random()*modelNames.length)];
};

const randomDroneModel = () => {
  return `${randomManufacturerName()} ${randomModelName()}`;
};

/**
 * Returns a random rating between 1.0 and 5.0
 *
 * @returns {Number} A floating point number representing a rating between 1.0 and 5.0
 */
const randomRating = () => {
  const rating = ((Math.random() * 4) + 1).toFixed(1);
  return parseFloat(rating);
};

const randomMissionsCompleted = () => {
  const missionsCompleted = Math.floor(Math.random() * (90 - 4) + 4);
  return {
    missionsCompleted: missionsCompleted,
    missionsCompleted7Days: Math.floor(Math.sqrt(missionsCompleted))
  };
};

/**
 * Returns random coordinates that are within a certain distance (in meters)
 * of a given coordinates.
 *
 * @param {{lat: Number, long: Number}} coords - Origin coordinate to generate new random coordinate next to
 * @param {Number} radius - Maximum distance in meters from origin coordinates to generate new coordinate
 * @returns {{lat: Number, long: Number}} A new object containing latitude and longitude
 */
const randomCoords = ({ coords, radius }) => {
  const angle = Math.random() * 2 * Math.PI;
  const distance = Math.random() * radius;
  const longDegreesPerMeter = 1 / 111321.377778; // longitude degrees per meter
  const latDegreesPerMeter = 1 / 111134.86111; // latitude degrees per meter
  const x = parseFloat((coords.lat + latDegreesPerMeter * distance * Math.cos(angle)).toFixed(6));
  const y = parseFloat((coords.long + longDegreesPerMeter * distance * Math.sin(angle)).toFixed(6));
  return { lat: x, long: y };
};

module.exports = {
  randomDavAddress,
  randomDroneModel,
  randomRating,
  randomMissionsCompleted,
  randomCoords,
};
<commit_msg>Update random.js<commit_after>const randomString = require('randomstring');

const manufacturerNames = ['DJX', 'Parakeet', 'Gruff', 'Unique', 'FlyHawk'];
const modelNames = ['CargoMate', 'Postman', 'ShipIt', 'Air Ship'];

const randomDavAddress = () => {
  return '0x'+randomString.generate({
    length: 40,
    charset: 'hex'
  });
};

/**
 * Returns a random manufacturer name chosen from an array of possible names
 * @return {String} A string representing the name of a manufacturer
 */
const randomManufacturerName = () => {
  return manufacturerNames[Math.floor(Math.random()*manufacturerNames.length)];
};

const randomModelName = () => {
  return modelNames[Math.floor(Math.random()*modelNames.length)];
};

const randomDroneModel = () => {
  return `${randomManufacturerName()} ${randomModelName()}`;
};

/**
 * Returns a random rating between 1.0 and 5.0
 *
 * @returns {Number} A floating point number representing a rating between 1.0 and 5.0
 */
const randomRating = () => {
  const rating = ((Math.random() * 4) + 1).toFixed(1);
  return parseFloat(rating);
};

const randomMissionsCompleted = () => {
  const missionsCompleted = Math.floor(Math.random() * (90 - 4) + 4);
  return {
    missionsCompleted: missionsCompleted,
    missionsCompleted7Days: Math.floor(Math.sqrt(missionsCompleted))
  };
};

/**
 * Returns random coordinates that are within a certain distance (in meters)
 * of a given coordinates.
 *
 * @param {{lat: Number, long: Number}} coords - Origin coordinate to generate new random coordinate next to
 * @param {Number} radius - Maximum distance in meters from origin coordinates to generate new coordinate
 * @returns {{lat: Number, long: Number}} A new object containing latitude and longitude
 */
const randomCoords = ({ coords, radius }) => {
  const angle = Math.random() * 2 * Math.PI;
  const distance = Math.random() * radius;
  const longDegreesPerMeter = 1 / 111321.377778; // longitude degrees per meter
  const latDegreesPerMeter = 1 / 111134.86111; // latitude degrees per meter
  const x = parseFloat((coords.lat + latDegreesPerMeter * distance * Math.cos(angle)).toFixed(6));
  const y = parseFloat((coords.long + longDegreesPerMeter * distance * Math.sin(angle)).toFixed(6));
  return { lat: x, long: y };
};

module.exports = {
  randomDavAddress,
  randomDroneModel,
  randomRating,
  randomMissionsCompleted,
  randomCoords,
};
<|endoftext|>


<commit_before>window.InputController = (() => {
  return {
    init: () => {
      const token = window.sessionStorage.getItem('userInfo-token');
      $.getScript('js/caseFieldFunctionality.js', () => {
        function submitVictimForm(existingVictimInput) {
          if (!existingVictimInput) {
            return $.ajax({
              url: 'http://localhost:3000/victims',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                victName: {
                  first: caseUI.fields['victFirstName']['input'].val(),
                  middle: caseUI.fields['victMiddleName']['input'].val(),
                  last: caseUI.fields['victLastName']['input'].val()
                },
                victSex: caseUI.fields['victSex']['input'].val(),
                victDesc: caseUI.fields['victDesc']['input'].val(),
                victAge: caseUI.fields['victAge']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  didAPICallFail = true;
                  $('#victimFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#victimFormLabel').addClass('text-danger');
                  console.log('Victim submission failed:');
                  console.log(err);
                },
                201: (victim) => {
                  victimJSON = victim;
                  $('#victimFormSmall').text('');
                  $('#victimFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingVictimInput; // TODO: change?
        }

        function submitSuspectForm(existingSuspectInput) {
          if (!existingSuspectInput) {
            return $.ajax({
              url: 'http://localhost:3000/suspects',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                suspName: {
                  first: caseUI.fields['suspFirstName']['input'].val(),
                  middle: caseUI.fields['suspMiddleName']['input'].val(),
                  last: caseUI.fields['suspLastName']['input'].val()
                },
                suspSex: caseUI.fields['suspSex']['input'].val(),
                supervisedReleaseStatus: caseUI.fields['suspSupervisedReleaseStatus']['input'].val(),
                suspDesc: caseUI.fields['suspDesc']['input'].val(),
                suspAge: caseUI.fields['suspAge']['input'].val(),
                juvenileTriedAsAdult: caseUI.fields['juvenileTriedAsAdult']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  // TODO: commented out?
                  // didAPICallFail = true;
                  $('#suspectFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#suspectFormLabel').addClass('text-danger');
                  console.log('Suspect submission failed:');
                  console.log(err);
                },
                201: (suspect) => {
                  // TODO: commented out?
                  // suspectJSON = suspect;
                  $('#suspectFormSmall').text('');
                  $('#suspectFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingSuspectInput; // TODO: change?
        }

        function submitCaseForm(victimId, suspectIds) {
          return $.ajax({
            url: 'http://localhost:3000/cases',
            type: 'POST',
            headers: {
              'x-access-token': token
            },
            data: {
              drNumber: caseUI.fields['drNum']['input'].val(),
              masterDrNumber: caseUI.fields['masterDrNum']['input'].val(),
              division: caseUI.fields['division']['input'].val(),
              bureau: caseUI.fields['bureau']['input'].val(),
              notes: caseUI.fields['notes']['input'].val(),
              dateOccured: (new Date(caseUI.fields['dateOccured']['input'].val())).toISOString(),
              dateReported: (new Date(caseUI.fields['dateReported']['input'].val())).toISOString(),
              reportingDistrict: caseUI.fields['reportingDistrict']['input'].val(),
              caseStatus: caseUI.fields['caseStatus']['input'].val(),
              caseStatusDate: (new Date(caseUI.fields['caseStatusDate']['input'].val())).toISOString(),
              solvabilityFactor: caseUI.fields['solvabilityFactor']['input'].val(),
              weaponUsed: (function getWeaponsUsed() {
                const weaponsList = [];
                const weaponInputs = Object.keys(caseUI.fields['weapon']['inputs']);
                weaponInputs.forEach((weaponCheckbox) => {
                  if (caseUI.fields['weapon']['inputs'][weaponCheckbox].prop('checked')) {
                    weaponsList.push(caseUI.fields['weapon']['inputs'][weaponCheckbox].attr('name'));
                  }
                });
                return weaponsList;
              }()),
              motive: (function getMotives() {
                const motivesList = [];
                const motiveInputs = Object.keys(caseUI.fields['motive']['inputs']);
                motiveInputs.forEach((motiveCheckbox) => {
                  if (caseUI.fields['motive']['inputs'][motiveCheckbox].prop('checked')) {
                    motivesList.push(caseUI.fields['motive']['inputs'][motiveCheckbox].attr('name'));
                  }
                });
                return motivesList;
              }()),
              lastModifiedDate: (new Date()).toISOString(),
              lastModifiedBy: '5a07dcad41156921c81b70e4', // TODO: Get userId of user logged in
              victim: victimId,
              address: {
                streetNumber: caseUI.fields['streetNumber']['input'].val(),
                streetName: caseUI.fields['streetName']['input'].val(),
                city: caseUI.fields['city']['input'].val(),
                zipCode: caseUI.fields['zipCode']['input'].val()
              },
              suspects: [suspectIds]
            },
            statusCode: {
              400: (err) => {
                console.log('Case submission failed:');
                console.log(caseJSON);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database errors. ${err['responseJSON']['errors']['message']}`);
              },
              404: (err) => {
                console.log('Case submission failed:');
                console.log(err);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database error. ${err['responseJSON']['text']}: ${err['responseJSON']['value']}.`);
              },
              201: (caseJSON) => {
                console.log('Case submission results:');
                console.log(caseJSON);
                $('#submitFormSmall').removeClass('text-danger');
                $('#submitFormSmall').addClass('text-success');
                $('#submitFormSmall').text(`Case submission succeeded with DR# ${caseUI.fields['drNum']['input'].val()}.`);
                clearAllInputs();
              }
            }
          });
        }

        function attemptMasterFormSubmission() {
          if (caseUI.checkFormValidityAndAnnotate()) {
            const existingVictimID = caseUI.fields['newOrExistingVictim']['input'].val() === 'old' ?
              caseUI.fields['victId']['input'].val() : null; // pass in an existing ID or null.
            const existingSuspectID = caseUI.fields['newOrExistingSuspect']['input'].val() === 'old' ?
              caseUI.fields['suspId']['input'].val() : null; // pass in an existing ID or null.

            Promise.all([submitVictimForm(existingVictimID), submitSuspectForm(existingSuspectID)])
              .then((values) => {
                const victim = values[0]['_id'] || values[0];
                const suspect = values[1]['_id'] || values[1];
                console.log('victim: ', victim);
                submitCaseForm(victim, suspect);
              }).catch((err) => {
                console.log(err);
              });
          }
        }

        $('#button-submit-forms').on('click', () => {
          attemptMasterFormSubmission();
        });

        function clearAllInputs() {
          for (field in caseUI.fields) {
            if (caseUI.fields[field]['input'] === undefined) {
              for (input in caseUI.fields[field]['inputs']) {
                caseUI.fields[field]['inputs'][input].prop('checked', false);
              }
            } else {
              caseUI.fields[field]['input'].val('');
            }
          }
          caseUI.newOrExistingSuspectInput.val('default');
          updateSuspectInputsVisibility();
          caseUI.newOrExistingVictimInput.val('default');
          updateVictimInputsVisibility();
        }

        function updateVictimInputsVisibility() {
          const val = caseUI.newOrExistingVictimInput.val();
          if (val === 'default') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.hide();
          } else if (val === 'new') {
            caseUI.newVictimForm.show();
            caseUI.existingVictimForm.hide();
          } else if (val === 'old') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.show();
          }
        }
        updateVictimInputsVisibility();

        // function updateSuspectInputsVisibility() {
        //   const val = caseUI.newOrExistingSuspectInput.val();
        //   if (val === 'default') {
        //     caseUI.newSuspectForm.hide();
        //     caseUI.existingSuspectForm.hide();
        //   } else if (val === 'new') {
        //     caseUI.newSuspectForm.show();
        //     caseUI.existingSuspectForm.hide();
        //   } else if (val === 'old') {
        //     caseUI.newSuspectForm.hide();
        //     caseUI.existingSuspectForm.show();
        //   }
        // }

        function updateSuspectInputsVisibility(input, newSusForm, existSusForm) {
          console.log('Input: ', input);
          console.log('Form: ', newSusForm);
          const val = (!input ? caseUI.newOrExistingSuspectInput : input).val();
          const newSuspectForm = (!newSusForm ? caseUI.newSuspectForm : newSusForm);
          const existingSuspectForm = (!existSusForm ? caseUI.existingSuspectForm : existSusForm);
          console.log('Val: ', val);
          console.log('newSuspectForm: ', newSuspectForm);
          console.log('existSuspectForm: ', existingSuspectForm);

          if (val === 'default') {
            newSuspectForm.hide();
            existingSuspectForm.hide();
          } else if (val === 'new') {
            newSuspectForm.show();
            existingSuspectForm.hide();
          } else if (val === 'old') {
            newSuspectForm.hide();
            existingSuspectForm.show();
          }
        }

        updateSuspectInputsVisibility();

        caseUI.newOrExistingVictimInput.change(() => {
          updateVictimInputsVisibility();
        });

        caseUI.newOrExistingSuspectInput.change(() => {
          updateSuspectInputsVisibility();
        });

        const newOrExistingSuspectChangeHandler = function handler(input) {
          const $this = input;
          console.log('THIS: ', $this);
          // console.log('Handler i: ', i);
          // const input = $(`#newOrExistingSuspectInput.${i}`);
          const $associatedNewForm = $this.data('associatedNewSuspectForm');
          const $associatedExistingForm = $this.data('associatedExistingSuspectForm');
          console.log('Handler New Form: ', $associatedNewForm);
          console.log('Handler Existing Form: ', $associatedExistingForm);
          updateSuspectInputsVisibility($this, $associatedNewForm, $associatedExistingForm);
          // const $this = $(`#newOrExistingSuspectInput.${i}`);
          // $associatedForm = $this.data('associatedForm');
        };

        let i = 0;
        function duplicateSuspectForm() {
          const spacer = $('.casex-spacer').clone();

          const selectorParent = $('#newOrExistingSuspectInput').parent().parent();
          const newSelector = selectorParent.clone();
          const selector = newSelector.find('#newOrExistingSuspectInput');
          selector.attr({ id: 'newOrExistingSuspectInput' }).addClass(`${i}`);

          const newSusForm = $('#newSuspectForm');
          const newNewForm = newSusForm.clone();
          let formParent = newSusForm.parent();
          newNewForm.attr({ id: 'newSuspectForm', style: 'display: none' }).addClass(`${i}`);

          selector.data({ associatedNewSuspectForm: newNewForm });

          const existSusForm = $('#existingSuspectForm');
          const newExistForm = existSusForm.clone();
          formParent = existSusForm.parent();
          newExistForm.attr({ id: 'existingSuspectForm', style: 'display: none' }).addClass(`${i}`);
          formParent.append(spacer);
          formParent.append(newSelector);
          formParent.append(newNewForm);
          formParent.append(newExistForm);

          selector.data({ associatedExistingSuspectForm: newExistForm });

          $(`#newOrExistingSuspectInput.${i}`).change(function change() {
            newOrExistingSuspectChangeHandler($(this));
          });

          i += 1;

          // console.log(caseUI.newOrExistingSuspectInput);

          // - Use selector.data to directly link created selector to created form.
          // - Then create change handler in page-input.js (line 256)
          // - Call the handler upon completion to handle the results
          // - Good luck
        }

        $('#button-add-suspect').click(() => {
          duplicateSuspectForm();
        });

        // $('[id="newOrExistingSuspectInput"]').change(function() {
        // // $(caseUI).change('newOrExistingSuspectInput', function() {
        // //   console.log($('[id="newOrExistingSuspectInput"]'));
        // //   // console.log($(this));
        // //   $('#newOrExistingSuspectInput').each(function sus(i) {
        // //     console.log(i, ': ', $(this));
        // //   });
        //   updateSuspectInputsVisibility();
        // });
      });
    }
  };
})();
<commit_msg>Can add multiple existing suspects<commit_after>window.InputController = (() => {
  return {
    init: () => {
      const token = window.sessionStorage.getItem('userInfo-token');
      $.getScript('js/caseFieldFunctionality.js', () => {
        function submitVictimForm(existingVictimInput) {
          if (!existingVictimInput) {
            return $.ajax({
              url: 'http://localhost:3000/victims',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                victName: {
                  first: caseUI.fields['victFirstName']['input'].val(),
                  middle: caseUI.fields['victMiddleName']['input'].val(),
                  last: caseUI.fields['victLastName']['input'].val()
                },
                victSex: caseUI.fields['victSex']['input'].val(),
                victDesc: caseUI.fields['victDesc']['input'].val(),
                victAge: caseUI.fields['victAge']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  didAPICallFail = true;
                  $('#victimFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#victimFormLabel').addClass('text-danger');
                  console.log('Victim submission failed:');
                  console.log(err);
                },
                201: (victim) => {
                  victimJSON = victim;
                  $('#victimFormSmall').text('');
                  $('#victimFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingVictimInput; // TODO: change?
        }

        function submitSuspectForm(existingSuspectInput) {
          if (!existingSuspectInput) {
            return $.ajax({
              url: 'http://localhost:3000/suspects',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                suspName: {
                  first: caseUI.fields['suspFirstName']['input'].val(),
                  middle: caseUI.fields['suspMiddleName']['input'].val(),
                  last: caseUI.fields['suspLastName']['input'].val()
                },
                suspSex: caseUI.fields['suspSex']['input'].val(),
                supervisedReleaseStatus: caseUI.fields['suspSupervisedReleaseStatus']['input'].val(),
                suspDesc: caseUI.fields['suspDesc']['input'].val(),
                suspAge: caseUI.fields['suspAge']['input'].val(),
                juvenileTriedAsAdult: caseUI.fields['juvenileTriedAsAdult']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  // TODO: commented out?
                  // didAPICallFail = true;
                  $('#suspectFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#suspectFormLabel').addClass('text-danger');
                  console.log('Suspect submission failed:');
                  console.log(err);
                },
                201: (suspect) => {
                  // TODO: commented out?
                  // suspectJSON = suspect;
                  $('#suspectFormSmall').text('');
                  $('#suspectFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingSuspectInput; // TODO: change?
        }

        function submitCaseForm(victimId, suspectIds) {
          console.log('case ids: ', suspectIds);
          return $.ajax({
            url: 'http://localhost:3000/cases',
            type: 'POST',
            headers: {
              'x-access-token': token
            },
            data: {
              drNumber: caseUI.fields['drNum']['input'].val(),
              masterDrNumber: caseUI.fields['masterDrNum']['input'].val(),
              division: caseUI.fields['division']['input'].val(),
              bureau: caseUI.fields['bureau']['input'].val(),
              notes: caseUI.fields['notes']['input'].val(),
              dateOccured: (new Date(caseUI.fields['dateOccured']['input'].val())).toISOString(),
              dateReported: (new Date(caseUI.fields['dateReported']['input'].val())).toISOString(),
              reportingDistrict: caseUI.fields['reportingDistrict']['input'].val(),
              caseStatus: caseUI.fields['caseStatus']['input'].val(),
              caseStatusDate: (new Date(caseUI.fields['caseStatusDate']['input'].val())).toISOString(),
              solvabilityFactor: caseUI.fields['solvabilityFactor']['input'].val(),
              weaponUsed: (function getWeaponsUsed() {
                const weaponsList = [];
                const weaponInputs = Object.keys(caseUI.fields['weapon']['inputs']);
                weaponInputs.forEach((weaponCheckbox) => {
                  if (caseUI.fields['weapon']['inputs'][weaponCheckbox].prop('checked')) {
                    weaponsList.push(caseUI.fields['weapon']['inputs'][weaponCheckbox].attr('name'));
                  }
                });
                return weaponsList;
              }()),
              motive: (function getMotives() {
                const motivesList = [];
                const motiveInputs = Object.keys(caseUI.fields['motive']['inputs']);
                motiveInputs.forEach((motiveCheckbox) => {
                  if (caseUI.fields['motive']['inputs'][motiveCheckbox].prop('checked')) {
                    motivesList.push(caseUI.fields['motive']['inputs'][motiveCheckbox].attr('name'));
                  }
                });
                return motivesList;
              }()),
              lastModifiedDate: (new Date()).toISOString(),
              lastModifiedBy: '5a07dcad41156921c81b70e4', // TODO: Get userId of user logged in
              victim: victimId,
              address: {
                streetNumber: caseUI.fields['streetNumber']['input'].val(),
                streetName: caseUI.fields['streetName']['input'].val(),
                city: caseUI.fields['city']['input'].val(),
                zipCode: caseUI.fields['zipCode']['input'].val()
              },
              suspects: suspectIds
            },
            statusCode: {
              400: (err) => {
                console.log('Case submission failed:');
                console.log(caseJSON);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database errors. ${err['responseJSON']['errors']['message']}`);
              },
              404: (err) => {
                console.log('Case submission failed:');
                console.log(err);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database error. ${err['responseJSON']['text']}: ${err['responseJSON']['value']}.`);
              },
              201: (caseJSON) => {
                console.log('Case submission results:');
                console.log(caseJSON);
                $('#submitFormSmall').removeClass('text-danger');
                $('#submitFormSmall').addClass('text-success');
                $('#submitFormSmall').text(`Case submission succeeded with DR# ${caseUI.fields['drNum']['input'].val()}.`);
                clearAllInputs();
              }
            }
          });
        }

        function attemptMasterFormSubmission() {
          if (caseUI.checkFormValidityAndAnnotate()) {
            const existingVictimID = caseUI.fields['newOrExistingVictim']['input'].val() === 'old' ?
              caseUI.fields['victId']['input'].val() : null; // pass in an existing ID or null.
            const existingSuspectID = caseUI.fields['newOrExistingSuspect']['input'].val() === 'old' ?
              caseUI.fields['suspId']['input'].val() : null; // pass in an existing ID or null.

            const existingSuspectIDs = [];
            // $('[id="suspIdInput"]').each(function each() {
            //   console.log($(this));
            //   existingSuspectIDs.push($(this).val());
            // });

            $('[id="newOrExistingSuspectInput"]').each(function each() {
              if ($(this).val() === 'old') {
                const index = $(this).attr('class').split(' ')[1] ? +$(this).attr('class').split(' ')[1] : null;
                existingSuspectIDs.push($(`#existingSuspectForm${index ? `.${index}` : ''}`).find('#suspIdInput').val());
              }
            });

            console.log('suspects: ', existingSuspectIDs);

            Promise.all([submitVictimForm(existingVictimID), submitSuspectForm(existingSuspectIDs)])
              .then((values) => {
                console.log('values: ', values);
                const victim = values[0]['_id'] || values[0];
                const suspect = values[1]['_id'] || values[1];
                console.log('victim: ', victim);
                submitCaseForm(victim, suspect);
              }).catch((err) => {
                console.log(err);
              });
          }
        }

        $('#button-submit-forms').on('click', () => {
          attemptMasterFormSubmission();
        });

        function clearAllInputs() {
          for (field in caseUI.fields) {
            if (caseUI.fields[field]['input'] === undefined) {
              for (input in caseUI.fields[field]['inputs']) {
                caseUI.fields[field]['inputs'][input].prop('checked', false);
              }
            } else {
              caseUI.fields[field]['input'].val('');
            }
          }
          caseUI.newOrExistingSuspectInput.val('default');
          updateSuspectInputsVisibility();
          caseUI.newOrExistingVictimInput.val('default');
          updateVictimInputsVisibility();
        }

        function updateVictimInputsVisibility() {
          const val = caseUI.newOrExistingVictimInput.val();
          if (val === 'default') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.hide();
          } else if (val === 'new') {
            caseUI.newVictimForm.show();
            caseUI.existingVictimForm.hide();
          } else if (val === 'old') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.show();
          }
        }
        updateVictimInputsVisibility();

        // function updateSuspectInputsVisibility() {
        //   const val = caseUI.newOrExistingSuspectInput.val();
        //   if (val === 'default') {
        //     caseUI.newSuspectForm.hide();
        //     caseUI.existingSuspectForm.hide();
        //   } else if (val === 'new') {
        //     caseUI.newSuspectForm.show();
        //     caseUI.existingSuspectForm.hide();
        //   } else if (val === 'old') {
        //     caseUI.newSuspectForm.hide();
        //     caseUI.existingSuspectForm.show();
        //   }
        // }

        function updateSuspectInputsVisibility(input, newSusForm, existSusForm) {
          // console.log('Input: ', input);
          // console.log('Form: ', newSusForm);
          const val = (!input ? caseUI.newOrExistingSuspectInput : input).val();
          const newSuspectForm = (!newSusForm ? caseUI.newSuspectForm : newSusForm);
          const existingSuspectForm = (!existSusForm ? caseUI.existingSuspectForm : existSusForm);
          // console.log('Val: ', val);
          // console.log('newSuspectForm: ', newSuspectForm);
          // console.log('existSuspectForm: ', existingSuspectForm);

          if (val === 'default') {
            newSuspectForm.hide();
            existingSuspectForm.hide();
          } else if (val === 'new') {
            newSuspectForm.show();
            existingSuspectForm.hide();
          } else if (val === 'old') {
            newSuspectForm.hide();
            existingSuspectForm.show();
          }
        }

        updateSuspectInputsVisibility();

        caseUI.newOrExistingVictimInput.change(() => {
          updateVictimInputsVisibility();
        });

        caseUI.newOrExistingSuspectInput.change(() => {
          updateSuspectInputsVisibility();
        });

        const newOrExistingSuspectChangeHandler = function handler(input) {
          const $this = input;
          // console.log('THIS: ', $this);
          // console.log('Handler i: ', i);
          // const input = $(`#newOrExistingSuspectInput.${i}`);
          const $associatedNewForm = $this.data('associatedNewSuspectForm');
          const $associatedExistingForm = $this.data('associatedExistingSuspectForm');
          // console.log('Handler New Form: ', $associatedNewForm);
          // console.log('Handler Existing Form: ', $associatedExistingForm);
          updateSuspectInputsVisibility($this, $associatedNewForm, $associatedExistingForm);
          // const $this = $(`#newOrExistingSuspectInput.${i}`);
          // $associatedForm = $this.data('associatedForm');
        };

        let i = 0;
        function duplicateSuspectForm() {
          const spacer = $('.casex-spacer').clone();

          const selectorParent = $('#newOrExistingSuspectInput').parent().parent();
          const newSelector = selectorParent.clone();
          const selector = newSelector.find('#newOrExistingSuspectInput');
          selector.attr({ id: 'newOrExistingSuspectInput' }).addClass(`${i}`);

          const newSusForm = $('#newSuspectForm');
          const newNewForm = newSusForm.clone();
          let formParent = newSusForm.parent();
          newNewForm.attr({ id: 'newSuspectForm', style: 'display: none' }).addClass(`${i}`);

          selector.data({ associatedNewSuspectForm: newNewForm });

          const existSusForm = $('#existingSuspectForm');
          const newExistForm = existSusForm.clone();
          formParent = existSusForm.parent();
          newExistForm.attr({ id: 'existingSuspectForm', style: 'display: none' }).addClass(`${i}`);
          formParent.append(spacer);
          formParent.append(newSelector);
          formParent.append(newNewForm);
          formParent.append(newExistForm);

          selector.data({ associatedExistingSuspectForm: newExistForm });

          $(`#newOrExistingSuspectInput.${i}`).change(function change() {
            newOrExistingSuspectChangeHandler($(this));
          });

          i += 1;

          // console.log(caseUI.newOrExistingSuspectInput);

          // - Use selector.data to directly link created selector to created form.
          // - Then create change handler in page-input.js (line 256)
          // - Call the handler upon completion to handle the results
          // - Good luck
        }

        $('#button-add-suspect').click(() => {
          duplicateSuspectForm();
        });

        // $('[id="newOrExistingSuspectInput"]').change(function() {
        // // $(caseUI).change('newOrExistingSuspectInput', function() {
        // //   console.log($('[id="newOrExistingSuspectInput"]'));
        // //   // console.log($(this));
        // //   $('#newOrExistingSuspectInput').each(function sus(i) {
        // //     console.log(i, ': ', $(this));
        // //   });
        //   updateSuspectInputsVisibility();
        // });
      });
    }
  };
})();
<|endoftext|>


<commit_before>// Copyright 2013-2016, University of Colorado Boulder

/**
 * A DerivedProperty is computed based on other Properties.  This implementation inherits from Property to (a) simplify
 * implementation and (b) ensure it remains consistent. Note that the setters should not be called directly, so the
 * setters (set, reset and es5 setter) throw an error if used directly.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var DerivedPropertyIO = require( 'AXON/DerivedPropertyIO' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Property = require( 'AXON/Property' );
  var Tandem = require( 'TANDEM/Tandem' );

  /**
   * @param {Property[]} dependencies - Properties that this Property's value is derived from
   * @param {function} derivation - function that derives this Property's value, expects args in the same order as dependencies
   * @param {Object} [options] - see Property
   * @constructor
   */
  function DerivedProperty( dependencies, derivation, options ) {

    options = _.extend( {
      tandem: Tandem.optional,
      phetioType: null, // must be supplied by instantiations and must be of type DerivedPropertyIO
      phetioReadOnly: true // derived properties can be read but not set by PhET-iO
    }, options );

    if ( options.tandem.isSuppliedAndEnabled() ) {

      // The phetioType should be a concrete (instantiated) DerivedPropertyIO, hence we must check its outer type
      assert && assert( options.phetioType.outerType === DerivedPropertyIO, 'phetioType should be DerivedPropertyIO' );
    }

    this.dependencies = dependencies; // @private

    var initialValue = derivation.apply( null, dependencies.map( function( property ) {return property.get();} ) );

    // We must pass supertype tandem to parent class so addInstance is called only once in the subclassiest constructor.
    Property.call( this, initialValue, options );

    var self = this;

    // @private Keep track of listeners so they can be detached
    this.dependencyListeners = [];

    for ( var i = 0; i < dependencies.length; i++ ) {
      var dependency = dependencies[ i ];
      ( function( dependency ) {
        var listener = function() {
          Property.prototype.set.call( self, derivation.apply( null, dependencies.map( function( property ) {return property.get();} ) ) );
        };
        self.dependencyListeners.push( listener );
        dependency.lazyLink( listener );
      } )( dependency, i );
    }
  }

  axon.register( 'DerivedProperty', DerivedProperty );

  function equalsFunction( a, b ) {
    return a === b;
  }

  function andFunction( value, property ) {
    assert && assert( typeof property.value === 'boolean', 'boolean value required' );
    return value && property.value;
  }

  function orFunction( value, property ) {
    assert && assert( typeof property.value === 'boolean', 'boolean value required' );
    return value || property.value;
  }

  return inherit( Property, DerivedProperty, {

    // @public
    dispose: function() {

      // Unlink from dependent Properties
      for ( var i = 0; i < this.dependencies.length; i++ ) {
        var dependency = this.dependencies[ i ];
        dependency.unlink( this.dependencyListeners[ i ] );
      }
      this.dependencies = null;
      this.dependencyListeners = null;

      Property.prototype.dispose.call( this );
    },

    /**
     * Override the mutators to provide an error message.  These should not be called directly,
     * the value should only be modified when the dependencies change.
     * @param value
     * @override
     * @public
     */
    set: function( value ) { throw new Error( 'Cannot set values directly to a DerivedProperty, tried to set: ' + value ); },

    /**
     * Override the mutators to provide an error message.  These should not be called directly, the value should only be modified
     * when the dependencies change. Keep the newValue output in the string so the argument won't be stripped by minifier
     * (which would cause crashes like https://github.com/phetsims/axon/issues/15)
     * @param newValue
     * @override
     * @public
     */
    set value( newValue ) { throw new Error( 'Cannot es5-set values directly to a DerivedProperty, tried to set: ' + newValue ); },

    /**
     * Override the mutators to provide an error message.  These should not be called directly,
     * the value should only be modified when the dependencies change.
     * @override
     * @public
     */
    reset: function() { throw new Error( 'Cannot reset a DerivedProperty directly' ); },

    /**
     * Override the getter for value as well, since we need the getter/setter pair to override the getter/setter pair in Property
     * (instead of a setter with no getter overriding). See https://github.com/phetsims/axon/issues/171 for more details
     * @returns {*}
     * @override
     * @public
     */
    get value() { return Property.prototype.get.call( this ); }
  }, {

    /**
     * Creates a derived boolean Property whose value is true iff firstProperty's value is equal to secondProperty's
     * value.
     * @public
     *
     * @param {Property.<*>} firstProperty
     * @param {Property.<*>} secondProperty
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    valueEquals: function( firstProperty, secondProperty, options ) {
      return new DerivedProperty( [ firstProperty, secondProperty ], equalsFunction, options );
    },

    /**
     * Creates a derived boolean Property whose value is true iff every input Property value is true.
     * @public
     *
     * @param {Array.<Property.<boolean>>} properties
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    and: function( properties, options ) {
      return new DerivedProperty( properties, _.reduce.bind( null, properties, andFunction, true ), options );
    },

    /**
     * Creates a derived boolean Property whose value is true iff any input Property value is true.
     * @public
     *
     * @param {Array.<Property.<boolean>>} properties
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    or: function( properties, options ) {
      return new DerivedProperty( properties, _.reduce.bind( null, properties, orFunction, false ), options );
    }
  } );
} );<commit_msg>don't removeListener on dependency if already disposed, see phetsims/sun#394<commit_after>// Copyright 2013-2016, University of Colorado Boulder

/**
 * A DerivedProperty is computed based on other Properties.  This implementation inherits from Property to (a) simplify
 * implementation and (b) ensure it remains consistent. Note that the setters should not be called directly, so the
 * setters (set, reset and es5 setter) throw an error if used directly.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var DerivedPropertyIO = require( 'AXON/DerivedPropertyIO' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Property = require( 'AXON/Property' );
  var Tandem = require( 'TANDEM/Tandem' );

  /**
   * @param {Property[]} dependencies - Properties that this Property's value is derived from
   * @param {function} derivation - function that derives this Property's value, expects args in the same order as dependencies
   * @param {Object} [options] - see Property
   * @constructor
   */
  function DerivedProperty( dependencies, derivation, options ) {

    options = _.extend( {
      tandem: Tandem.optional,
      phetioType: null, // must be supplied by instantiations and must be of type DerivedPropertyIO
      phetioReadOnly: true // derived properties can be read but not set by PhET-iO
    }, options );

    if ( options.tandem.isSuppliedAndEnabled() ) {

      // The phetioType should be a concrete (instantiated) DerivedPropertyIO, hence we must check its outer type
      assert && assert( options.phetioType.outerType === DerivedPropertyIO, 'phetioType should be DerivedPropertyIO' );
    }

    this.dependencies = dependencies; // @private

    var initialValue = derivation.apply( null, dependencies.map( function( property ) {return property.get();} ) );

    // We must pass supertype tandem to parent class so addInstance is called only once in the subclassiest constructor.
    Property.call( this, initialValue, options );

    var self = this;

    // @private Keep track of listeners so they can be detached
    this.dependencyListeners = [];

    for ( var i = 0; i < dependencies.length; i++ ) {
      var dependency = dependencies[ i ];
      ( function( dependency ) {
        var listener = function() {
          Property.prototype.set.call( self, derivation.apply( null, dependencies.map( function( property ) {return property.get();} ) ) );
        };
        self.dependencyListeners.push( listener );
        dependency.lazyLink( listener );
      } )( dependency, i );
    }
  }

  axon.register( 'DerivedProperty', DerivedProperty );

  function equalsFunction( a, b ) {
    return a === b;
  }

  function andFunction( value, property ) {
    assert && assert( typeof property.value === 'boolean', 'boolean value required' );
    return value && property.value;
  }

  function orFunction( value, property ) {
    assert && assert( typeof property.value === 'boolean', 'boolean value required' );
    return value || property.value;
  }

  return inherit( Property, DerivedProperty, {

    // @public
    dispose: function() {

      // Unlink from dependent Properties
      for ( var i = 0; i < this.dependencies.length; i++ ) {
        var dependency = this.dependencies[ i ];
        if ( !dependency.isDisposed ) {
          dependency.unlink( this.dependencyListeners[ i ] );
        }
      }
      this.dependencies = null;
      this.dependencyListeners = null;

      Property.prototype.dispose.call( this );
    },

    /**
     * Override the mutators to provide an error message.  These should not be called directly,
     * the value should only be modified when the dependencies change.
     * @param value
     * @override
     * @public
     */
    set: function( value ) { throw new Error( 'Cannot set values directly to a DerivedProperty, tried to set: ' + value ); },

    /**
     * Override the mutators to provide an error message.  These should not be called directly, the value should only be modified
     * when the dependencies change. Keep the newValue output in the string so the argument won't be stripped by minifier
     * (which would cause crashes like https://github.com/phetsims/axon/issues/15)
     * @param newValue
     * @override
     * @public
     */
    set value( newValue ) { throw new Error( 'Cannot es5-set values directly to a DerivedProperty, tried to set: ' + newValue ); },

    /**
     * Override the mutators to provide an error message.  These should not be called directly,
     * the value should only be modified when the dependencies change.
     * @override
     * @public
     */
    reset: function() { throw new Error( 'Cannot reset a DerivedProperty directly' ); },

    /**
     * Override the getter for value as well, since we need the getter/setter pair to override the getter/setter pair in Property
     * (instead of a setter with no getter overriding). See https://github.com/phetsims/axon/issues/171 for more details
     * @returns {*}
     * @override
     * @public
     */
    get value() { return Property.prototype.get.call( this ); }
  }, {

    /**
     * Creates a derived boolean Property whose value is true iff firstProperty's value is equal to secondProperty's
     * value.
     * @public
     *
     * @param {Property.<*>} firstProperty
     * @param {Property.<*>} secondProperty
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    valueEquals: function( firstProperty, secondProperty, options ) {
      return new DerivedProperty( [ firstProperty, secondProperty ], equalsFunction, options );
    },

    /**
     * Creates a derived boolean Property whose value is true iff every input Property value is true.
     * @public
     *
     * @param {Array.<Property.<boolean>>} properties
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    and: function( properties, options ) {
      return new DerivedProperty( properties, _.reduce.bind( null, properties, andFunction, true ), options );
    },

    /**
     * Creates a derived boolean Property whose value is true iff any input Property value is true.
     * @public
     *
     * @param {Array.<Property.<boolean>>} properties
     * @param {Object} [options] - Forwarded to the DerivedProperty
     * @returns {DerivedProperty.<boolean>}
     */
    or: function( properties, options ) {
      return new DerivedProperty( properties, _.reduce.bind( null, properties, orFunction, false ), options );
    }
  } );
} );<|endoftext|>


<commit_before><commit_msg>Intermediate progress on using learner_token, see https://github.com/phetsims/phet-io/issues/908<commit_after><|endoftext|>