Skip to content
Snippets Groups Projects
spniSelect.js 46.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • function hideSingleSelectionTable() {
        singleSelectHidden = !singleSelectHidden;
        if (singleSelectHidden) {
            $individualSelectTable.hide();
        }
        else {
            $individualSelectTable.show();
        }
    }
    
    /************************************************************
     * Hides the table on the single selection screen.
     ************************************************************/
    function hideGroupSelectionTable() {
        groupSelectHidden = !groupSelectHidden;
        if (groupSelectHidden) {
            $groupSelectTable.hide();
        }
        else {
            $groupSelectTable.show();
        }
    }
    
    
    
    function openSearchModal() {
        $searchModal.modal('show');
    }
    
    
    function closeSearchModal() {
    
        // perform the search and sort logic
        updateSelectableOpponents();
    
        
        // update
        updateIndividualSelectScreen();
    
        updateIndividualCountStats();
    
    }
    
    function changeSearchGender(gender) {
        chosenGender = gender;
        setActiveOption($searchGenderOptions, gender);
    
    }
    
    /************************************************************
     * Sorting Functions
     ************************************************************/
    
    /** 
     * Callback for Arrays.sort to sort an array of objects by the given field.
     * Prefixing "-" to a field will cause the sort to be done in reverse.
     * Examples:
     *   // sorts myArr by each element's first name (A-Z)
     *   myArr.sort(sortOpponentsByField("first")); 
     *   // sorts myArr by each element's last name (Z-A)
     *   myArr.sort(sortOpponentsByField("-last")); 
     */
    function sortOpponentsByField(field) {
        // check for prefix
        var order = 1; // 1 = forward, -1 = reversed
        if (field[0] === "-") { 
            order = -1;
            field = field.substr(1);
        }
        
        return function(opp1, opp2) {
            var compare = 0;
            if (opp1[field] < opp2[field]) {
                compare = -1;
            }
            else if (opp1[field] > opp2[field]) {
                compare = 1;
            }
            return order * compare;
        }
    }
    
    /**
     * Callback for Arrays.sort to sort an array of objects over multiple given fields.
     * Prefixing "-" to a field will cause the sort to be done in reverse.
     * This should allow more flexibility in the sorting order.
     * Example:
     *   // sorts myArr by each element's number of layers (low to high), 
     *   // and for elements whose layers are equivalent, sort them by first name (Z-A)
     *   myArr.sort(sortOpponentsByMultipleFields("layers", "-first")); 
     */
    function sortOpponentsByMultipleFields() {
        var fields = arguments; // retrieve the args passed in
        return function(opp1, opp2) {
            var i = 0;
            var compare = 0;
            // if both elements have the same field, check the next ones
            while (compare === 0 && i < fields.length) {
                compare = sortOpponentsByField(fields[i])(opp1, opp2);
                i++;
            }
            return compare;
        }
    }
    
    
    /** Event handler for the sort dropdown options. Fires when user clicks on a dropdown item. */
    $sortingOptionsItems.on("click", function(e) {
        sortingMode = $(this).find('a').html();
        $("#sort-dropdown-selection").html(sortingMode); // change the dropdown text to the selected option
    });
    
    /************************************************************
     * Word wrapping Functions
     ************************************************************/
    
    /**
     * Inserts a fixed-size HTML element with the specified text to allow the content 
     * to be either word-wrapped (if the text is long and spaces are present) 
     * or word-broken (if text is long and no spaces are present).
     */
    function wordWrapHtml(text) {
    
        text = text || "&nbsp;";
    
        return "<table class=\"wrap-text\"><tr><td>" + text + "</td></tr></table>";
    
    
    /************************************************************
     * Dynamic dialogue and image counting functions
     ************************************************************/
    
    
    /** Event handler for the individual selection screen credits button. */
    
    $individualCreditsButton.on('click', function(e) {
        updateIndividualCountStats()
    
    /** Event handler for the group selection screen credits button. */
    
    $groupCreditsButton.on('click', function(e) {
        updateGroupCountStats();
    
    /**
     * Loads and displays the number of unique dialogue lines and the number of pose images 
     * into the character's player object for those currently on the selection screen.
     * Only loads if the unique line count or image count is not known.
     */
    
    function updateOpponentCountStats(opponentArr, uiElements) {
    
        opponentArr.forEach(function(opp, idx) {
    
            // load behaviour file if line/image count is not known
    
            if (opp && (opp.uniqueLineCount === undefined || opp.posesImageCount === undefined)) {
    
                uiElements.countBoxes[idx].css("visibility", "visible");
    
                // retrieve line and image counts
    
                if (DEBUG) { 
                    console.log("[LineImageCount] Fetching counts for " + opp.label + " in slot " + idx); 
                }
    
                var countsPromise = Promise.resolve(fetchBehaviour(opp.folder));
    
                countsPromise.then(countLinesImages).then(function(response) {
                    opp.uniqueLineCount = response.numUniqueLines;
                    opp.posesImageCount = response.numPoses;
                    
                    // show line and image counts
    
                    if (DEBUG) { 
                        console.log("[LineImageCount] Loaded " + opp.label + " from behaviour: " + 
                          opp.uniqueLineCount + " lines, " + opp.posesImageCount + " images"); 
                    }
    
                    uiElements.lineLabels[idx].html(opp.uniqueLineCount);
                    uiElements.poseLabels[idx].html(opp.posesImageCount);
    
                // this character's counts were previously loaded
    
                    if (DEBUG) { 
                        console.log("[LineImageCount] Loaded previous count for " + opp.label + ": " + 
                          opp.uniqueLineCount + " lines, " + opp.posesImageCount + " images)"); 
                    }
    
                    uiElements.countBoxes[idx].css("visibility", "visible");
                    uiElements.lineLabels[idx].html(opp.uniqueLineCount);
                    uiElements.poseLabels[idx].html(opp.posesImageCount);
    
                    // there is no character in the slot
    
                    uiElements.countBoxes[idx].css("visibility", "hidden");
                    uiElements.lineLabels[idx].html("");
                    uiElements.poseLabels[idx].html("");
    
    /** Dialogue/image count update function for the individual selection screen. */
    function updateIndividualCountStats() {
        if (individualCreditsShown) {
    
            var individualUIElements = {
                countBoxes : $individualCountBoxes,
                lineLabels : $individualLineCountLabels,
                poseLabels : $individualPoseCountLabels
            };
            updateOpponentCountStats(shownIndividuals, individualUIElements);
    
        }
    }
    
    /** Dialogue/image count update function for the group selection screen. */
    function updateGroupCountStats() {
        if (groupCreditsShown) {
    
            var groupUIElements = {
                countBoxes : $groupCountBoxes,
                lineLabels : $groupLineCountLabels,
                poseLabels : $groupPoseCountLabels
            };
            updateOpponentCountStats(shownGroup, groupUIElements);
    
    /**
     * Fetches the behaviour.xml file of the specified opponent directory.
     */
    function fetchBehaviour(path) {
    
        return $.ajax({
            type: "GET",
            url: path + "behaviour.xml",
            dataType: "text"
        });
    }
    
    
    /**
     * Callback to parse the number of lines of dialogue and number of images
     * given a character's behaviour XML. Returns the counts as an object with 
     * properties numTotalLines, numUniqueLines, and numPoses.
     */
    
    function countLinesImages(xml) {
    
        // parse all lines of dialogue and all images
    
        $(xml).find('state').each(function(idx, data) {
    
            lines.push(data.textContent.trim());
    
            poses.push(data.getAttribute("img")); 
    
        
        // count only unique lines of dialogue
    
        var numUniqueDialogueLines = lines.filter(function(data, idx) {
            return idx == lines.lastIndexOf(data);
        }).length;
        
    
        // count unique number of poses used in dialogue
        // note that this number may differ from actual image count if some images
        // are never used, or if images that don't exist are used in the dialogue
        var numUniqueUsedPoses = poses.filter(function(data, idx) {
            return idx == poses.lastIndexOf(data);
        }).length;
        
    
        return {
            numTotalLines : lines.length,
            numUniqueLines : numUniqueDialogueLines,
    
            numPoses : numUniqueUsedPoses