mirror of
https://github.com/dmuth/diceware.git
synced 2024-11-21 16:36:28 -05:00
338 lines
8.2 KiB
JavaScript
338 lines
8.2 KiB
JavaScript
|
|
|
|
let lib = require("./lib.js")();
|
|
|
|
// Functions that relate to rolling dice
|
|
dice = require("./dice.js")();
|
|
|
|
wordlist = require("./wordlist.js")();
|
|
|
|
// Misc utilities
|
|
util = require("./util.js")();
|
|
|
|
let Promise = require("bluebird");
|
|
|
|
|
|
module.exports = function(arg) {
|
|
|
|
//
|
|
// Export our functions.
|
|
//
|
|
return({
|
|
rollDiceHandler: rollDiceHandler,
|
|
});
|
|
|
|
}
|
|
|
|
/**
|
|
* Dispaly all of our rows (dice rolls) and the results.
|
|
*/
|
|
function _rows(rows) {
|
|
|
|
//
|
|
// Now display those rows.
|
|
//
|
|
_row(rows, function() {
|
|
|
|
//
|
|
// And then display the results
|
|
//
|
|
results(function() {
|
|
|
|
//
|
|
// Set the height of this back to auto so we don't have unused space.
|
|
// I'm amazed that we don't see a "flash" of the results div
|
|
// temporarily shrinking, but this seems to work as per what I saw
|
|
// at http://stackoverflow.com/questions/5003220/javascript-jquery-animate-to-auto-height
|
|
//
|
|
// Well then.
|
|
//
|
|
let height = jQuery(".results").height();
|
|
jQuery(".results").css("height", "auto");
|
|
|
|
let new_height = jQuery(".results").height();
|
|
jQuery(".results").height(height);
|
|
jQuery(".results").animate({height: new_height}, 400);
|
|
|
|
//
|
|
// All done with our results, re-enable the button!
|
|
//
|
|
jQuery("#roll_dice").prop("disabled", false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} // End of _rows()
|
|
|
|
|
|
/**
|
|
* This function displays each dice roll.
|
|
*
|
|
* @param array rows Array of rows of dice rolls that we had.
|
|
* @param object cb Our callback to fire when done
|
|
* @param integer in_fadein_duration How long before fading in a roll of dice
|
|
* @param integer in_fadeout_delay How long before fading out the diceroll
|
|
*
|
|
*/
|
|
function _row(rows, cb, in_fadein_duration, in_fadeout_delay) {
|
|
|
|
let fadein_duration = in_fadein_duration || 250;
|
|
let fadeout_delay = in_fadeout_delay || 400;
|
|
|
|
if (rows.length) {
|
|
//
|
|
// Grab a row, and hide each of the dice and the word in it.
|
|
//
|
|
let row = rows.shift();
|
|
let html = row.hide().appendTo(".results");
|
|
html.find(".dice_element").each(function(i, value) {
|
|
jQuery(value).hide();
|
|
});
|
|
|
|
//
|
|
// Now show the row, and loop through each element, fading in
|
|
// the dice and the word in sequence.
|
|
//
|
|
html.show(fadein_duration, function() {
|
|
|
|
jQuery(this).find(".dice_element").each(function(i, value) {
|
|
let delay = i * 100;
|
|
setTimeout(function() {
|
|
jQuery(value).show();
|
|
}, delay);
|
|
|
|
});
|
|
|
|
//
|
|
// Decrease the delays with subsequent rolls so that users
|
|
// don't get impatent.
|
|
// (I know I did when rolling 8 dice!)
|
|
//
|
|
fadein_duration -= 25;
|
|
//fadeout_delay -= 50;
|
|
|
|
//
|
|
// Now fade out the entire row, and call ourselves again
|
|
// so we can repeat with the next row.
|
|
//
|
|
jQuery(this).delay(fadeout_delay)
|
|
.fadeOut(fadeout_delay, function() {
|
|
_row(rows, cb, fadein_duration, fadeout_delay);
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
//
|
|
// All done with displaying rows, fire our callback and get outta here.
|
|
//
|
|
cb();
|
|
|
|
}
|
|
|
|
} // End of row()
|
|
|
|
|
|
/**
|
|
* Display the actual results.
|
|
*
|
|
* @param cb object Optional callback to fire when done
|
|
*/
|
|
function results(cb) {
|
|
|
|
jQuery(".results_words_key").hide().clone().appendTo(".results");
|
|
jQuery(".results_words_value").hide().clone().appendTo(".results");
|
|
jQuery(".results").append("<br clear=\"all\" />");
|
|
|
|
jQuery(".results_phrase_key").hide().clone().appendTo(".results");
|
|
jQuery(".results_phrase_value").hide().clone().appendTo(".results");
|
|
jQuery(".results").append("<br clear=\"all\" />");
|
|
|
|
jQuery(".results_num_possible_key").hide().clone().appendTo(".results");
|
|
jQuery(".results_num_possible_value").hide().clone().appendTo(".results");
|
|
|
|
jQuery(".results .results_words_key").fadeIn(500).promise().then(function() {
|
|
return(jQuery(".results .results_words_value").fadeIn(500).promise())
|
|
}).then(function() {
|
|
return(jQuery(".results .results_phrase_key").fadeIn(400).promise());
|
|
}).then(function() {
|
|
return(jQuery(".results .results_phrase_value").fadeIn(400).promise());
|
|
}).then(function() {
|
|
return(jQuery(".results .results_num_possible_key").fadeIn(300).promise());
|
|
}).then(function() {
|
|
return(jQuery(".results .results_num_possible_value").fadeIn(300).promise());
|
|
}).then(function() {
|
|
if (cb) {
|
|
cb();
|
|
}
|
|
});
|
|
|
|
} // End of results()
|
|
|
|
|
|
/**
|
|
* Do some preliminary work, such as clearing out results and scrolling.
|
|
*/
|
|
function rollDiceHandlerPre() {
|
|
|
|
//
|
|
// Clear out more space when mobile
|
|
//
|
|
// In the future, I should just use a media query in CSS
|
|
//
|
|
let target_height = 300;
|
|
if (util.is_mobile()) {
|
|
target_height = 400;
|
|
}
|
|
|
|
jQuery(".results").animate({height: target_height}, 400);
|
|
|
|
//
|
|
// If we're running on an iPhone or similar, scroll down so that we can
|
|
// see the dice rolls and passphrase.
|
|
//
|
|
if (util.is_mobile()) {
|
|
let aTag = $("a[name='roll_dice_button']");
|
|
$("html,body").animate({scrollTop: aTag.offset().top}, "slow");
|
|
}
|
|
|
|
//
|
|
// Remove any old results
|
|
//
|
|
jQuery(".results").empty();
|
|
|
|
} // End of rollDiceHandlerPre()
|
|
|
|
|
|
/**
|
|
* Our handler for what to do when the "Roll Dice" button is clicked".
|
|
* It generates the passphrase and updates the HTML.
|
|
*/
|
|
function rollDiceHandler(e) {
|
|
|
|
//
|
|
// Disable our button while generating results
|
|
//
|
|
jQuery("#roll_dice").prop("disabled", true);
|
|
|
|
rollDiceHandlerPre();
|
|
|
|
//
|
|
// Make our dice rolls
|
|
//
|
|
let num_dice = jQuery(".dice_button.active").html();
|
|
console.log(`Rolling ${num_dice} dice...`);
|
|
let num_passwords = Number(Math.pow(6, (window.Diceware.num_dice_per_roll * num_dice)));
|
|
let passphrase = new Array();
|
|
let rolls = new Array();
|
|
|
|
//
|
|
// Create an array of empty items, since this is the only way I can
|
|
// figure out to do a loop in Bluebird at this time. Ugh.
|
|
//
|
|
let items = [];
|
|
for (i=0; i<num_dice; i++) { items.push(null); }
|
|
|
|
Promise.map(items, function(element) {
|
|
//
|
|
// Do our dice rolls all at once.
|
|
//
|
|
return(dice.rollDice(window.Diceware.num_dice_per_roll));
|
|
|
|
}).then(function(data) {
|
|
//
|
|
// Now that we have the results, get the word for each roll,
|
|
// save the roll, and push the word onto the passphrase.
|
|
//
|
|
data.forEach(function(row) {
|
|
|
|
let roll = {};
|
|
roll.dice = row;
|
|
//console.log("Debug Dice Roll", JSON.stringify(roll.dice)); // Debugging
|
|
roll.word = util.get_word(wordlist.get, roll.dice.value);
|
|
rolls.push(roll);
|
|
passphrase.push(roll.word);
|
|
|
|
});
|
|
|
|
//
|
|
// Store the number of dice rolled in a data attribute for
|
|
// inspection by Cypress or another test.
|
|
//
|
|
let results_num_dice = jQuery("#results-num-dice");
|
|
results_num_dice.text(num_dice);
|
|
|
|
rollDiceHandlerPost(rolls, passphrase, num_passwords);
|
|
|
|
});
|
|
|
|
} // End of rollDiceHandler()
|
|
|
|
|
|
/**
|
|
* Our post work, of displaying the results of our dice rolls.
|
|
*/
|
|
function rollDiceHandlerPost(rolls, passphrase, num_passwords) {
|
|
|
|
//
|
|
// Populate our results by cloning the hidden base rows which
|
|
// represent each die.
|
|
//
|
|
jQuery(".results_words_value").html(passphrase.join(" "));
|
|
//
|
|
// Separate words in the phrase by "Word Break Opportunity"
|
|
// tag so they will wrap properly on a narrow/mobile screen.
|
|
//
|
|
jQuery(".results_phrase_value").html(passphrase.join("<wbr>"));
|
|
//
|
|
// Convert the number of passwords to something based on the
|
|
// locale and then add in <wbr> tags so they too will wrap.
|
|
//
|
|
num_passwords = lib.convertBigNumberToString(num_passwords);
|
|
num_passwords_html = num_passwords.toLocaleString("fullwide");
|
|
num_passwords_html = num_passwords_html.replace(/,/g, ",<wbr>");
|
|
|
|
jQuery(".results_num_possible_value").html(num_passwords_html);
|
|
|
|
let rows = new Array();
|
|
for (let key in rolls) {
|
|
|
|
let roll = rolls[key];
|
|
let row = jQuery("<div></div>");
|
|
|
|
//
|
|
// Clone and append specific dice to this row.
|
|
//
|
|
for (let key2 in roll.dice.roll) {
|
|
let die = roll.dice.roll[key2];
|
|
let classname = ".source .dice" + die;
|
|
let tmp = jQuery(classname).clone().appendTo(row);
|
|
}
|
|
|
|
//
|
|
// Now append the word
|
|
//
|
|
let dice_word = jQuery(".dice_word").clone();
|
|
dice_word.html("\"" + roll.word + "\"");
|
|
row.append(dice_word);
|
|
|
|
//
|
|
// And clear to the next line
|
|
//
|
|
row.append("<br clear=\"all\" />");
|
|
|
|
if ("skip_animation" in window.Diceware.get_data) {
|
|
console.log("Debug value 'skip_animation' set, not showing the dice!");
|
|
} else {
|
|
rows.push(row);
|
|
}
|
|
|
|
}
|
|
|
|
_rows(rows);
|
|
|
|
} // End of rollDiceHandlerPost()
|
|
|
|
|
|
|