I'm trying to print an element, in my case an hr tag some number of times according to the length of a word. This code is for a hangman game I'm trying to recreate. I have looked up similar questions and its not quite what I'm lookin for.
This is my javascript code so far.
var words = ['Quaffle', 'Bludger', 'Golden Snitch', 'Time-Turner',
'Pensieve', 'Mirror of Erised'];
function getRandomWord(){
var randomIndex = words[Math.floor(Math.random()* words.length)];
alert(randomIndex);
}
function printDashes(){
var dashes = document.getElementById("dash")
}
getRandomWord()
printDashes()
I'm not sure what to add after retrieving the element. Can someone guide me on how to go about this?
You can also create div's so you can enter letters when the user inputs a character. I've attached an example below.
UPDATE: Added example code to update the dashes with letters based on word
var elem = document.getElementById('container');
var guess = document.getElementById('guess');
var word = "Hello";
// draw empty dashes
var drawDashes = function(numberOfDashes) {
for (var i = 0; i < numberOfDashes; i++) {
var el = document.createElement('div');
el.classList = 'dash';
// we draw an empty character inside so that the element
// doesn't adjust height when we update the dash later with a
// letter inside
el.innerHTML = ' ';
elem.appendChild(el);
}
}
// update dash with a letter based on index
var updateDash = function(index, letter) {
elem.children[index].innerHTML = letter;
}
guess.addEventListener('keyup', function(evt) {
// split the word up into characters
var splitWord = word.split('');
// check to see if the letter entered matches any of the
// words characters
for (var i = 0; i < splitWord.length; i++ ) {
// it is important we convert them to lowercase or
// else we might get a mismatch because of case-sensitivity
if (evt.key.toLowerCase() === splitWord[i].toLowerCase()) {
// update dash with letter based on index
updateDash(i, evt.key.toLowerCase());
}
}
// clear out the value
this.value = '';
});
drawDashes(word.length);
body {
font-family: sans-serif;
}
.dash {
height: 50px;
width: 50px;
margin: 0 10px;
display: inline-block;
border-bottom: 2px solid black;
font-size: 32px;
font-weight: bold;
text-align: center;
}
#guess {
height: 50px;
width: 50px;
padding: 0;
font-size: 32px;
text-align: center;
}
<div id="container"></div>
<h4>Type a letter</h4>
<input id="guess" type="text"/>
Say your word is in some variable named myWord.
Get the length of the word by doing:
var myWordLen = myWord.length;
Then you can create HTML elements using Javascript createElement method and appending child elements, information etc as needed. But since you want as many elements as the length of a word, use a loop. Eg:
for(var i=0; i < myWordLen; i++)
{
var tr1 = document.createElement("hr");
var someEle = document.getElementById("someID");
someEle.appendChild(tr1);
}
What about this way?
myElement.innerHTML = `<...>`.repeat(words.length)
Related
Been working on hangman using javascript and HTML, problem is whenever i click on a letter it doesn't replace the "_"
var myList=["Computer","Algorithm","Software","Programming","Developer"];
var n;
var star=" _";
console.log(myList)
computer=myList[Math.floor(Math.random() * myList.length)];
console.log(computer);
var word= document.getElementById("word").innerHTML=star.repeat(computer.length);
var letter=document.getElementsByClassName("col")
function myFunction(){
n=word.replace(star,letter);
};
for (var i=0; i<letter.length;i++){
letter[i].addEventListener("click",myFunction());
}
myFunction();
letter is basically alphabet(they are not buttons they are divs)
word is also an empty div in which the "-" goes in
in conclusion i want to replace word("-") with letters(which ever letter you click on)
Here is the working example:
var myList=["Computer","Algorithm","Software","Programming","Developer"];
var star="_";
var wrapper = document.querySelector('.wrapper');
for(var i = 0; i<myList.length; i++) {
var list = document.createElement('div');
list.setAttribute('class', 'wrapper-list');
list.setAttribute('id', 'list'+i);
wrapper.appendChild(list);
for(var j=0; j<myList[i].length;j++) {
var item = document.createElement('div');
item.setAttribute('class', 'wrapper-list__item');
item.innerText = myList[i][j];
list.appendChild(item);
item.onclick = function(e) {
this.innerText = star;
}
}
}
.wrapper .wrapper-list {
display: flex;
}
.wrapper .wrapper-list__item {
padding: 5px 10px;
border: 1px solid #dedede;
margin: 5px;
text-transform: uppercase;
cursor: pointer;
}
<div class="wrapper"></div>
I have many comma separated strings, each of which consists of a list of tags, and I want to style each tag inside a box (see here).
I converted each comma separated string ("p") into an array, then wrapped <span> tags around each value in the array, so I could style it with CSS, which worked great.
But whitespace strings are also getting wrapped in span tags which I do not want, I want to ignore those (or hide them).
How do I ignore those occurrences of "p" which contain only whitespace? The answers here and here but didn't work for me.
HTML:
<p>Skill 1, Skill 2, Skill 3</p>
<p>Skill 1</p>
<p> </p>
Javascript:
$("p").each(function() {
var words = $(this).text().split(", ");
var total = words.length;
$(this).empty();
for (index = 0; index < total; index++) {
$(this).append($("<span class = 'tag' > ").text(words[index]));
}
})
CSS:
.tag {
background-color: lightgray;
padding: 3px;
margin: 3px;
border-radius: 3px;
}
JS Fiddle
Just check to see if the trimmed text is truthy first. Also make sure not to implicitly create global variables, always declare variables with const (or let or var) before using them, otherwise errors will be thrown in strict mode:
if (words[index].trim()) {
$(this).append($("<span class = 'tag' > ").text(words[index]));
}
// Converts comma separated string into tags
function convertToTags(s) {
$(s).each(function() {
var words = $(this).text().split(", ");
var total = words.length;
$(this).empty();
for (let index = 0; index < total; index++) {
if (words[index].trim()) {
$(this).append($("<span class = 'tag' > ").text(words[index]));
}
}
})
}
// Calls the function on document ready
$(document).ready(function() {
convertToTags("p");
});
.tag {
background-color: lightgray;
padding: 3px;
margin: 3px;
border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>This, is, a, test</p>
<p>This</p>
<p> </p>
You need to apply your function only to the relevant elements.
In the following example I've used this condition:
$(this).text().trim().length > 0
$("p")
.each(function() {
const text = $(this).text().trim();
// This condition will make sure that "empty" p elements won't be affected
if (text.length > 0) {
var words = $(this).text().split(", ");
var total = words.length;
$(this).empty();
for (index = 0; index < total; index++) {
$(this).append($("<span class = 'tag' > ").text(words[index]));
}
}
})
.tag {
background-color: lightgray;
padding: 3px;
margin: 3px;
border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Skill 1, Skill 2, Skill 3 </p>
<p>Skill 1</p>
<p> </p>
function convertToTags(s) {
$("p").each(function() {
var text = $(this).text();
if(!text.replace(/ /g, '')){
$(this).remove();
return;
}
var words = text.split(", ");
var total = words.length;
$(this).empty();
for (index = 0; index < total; index++) {
$(this).append($("<span class = 'tag' > ").text(words[index]));
}
})
}
Magic lies in the first 2 statements within .each function. Before doing the split, we will check if there is anything else in this paragraph other than whitespace(s).
If not, remove this paragraph and start the next iteration.
I've started to make a memory game but I have a problem:
let card = [];
function makeCards() {
let cardSymbol = [];
const scorePan = document.querySelector('section');
scorePan.insertAdjacentHTML('afterend', '<ul class="deck"></ul>');
const cardDeck = document.querySelector('.deck');
for (let i = 1; i < 17; i++) {
card[i] = document.createElement('li');
card[i].setAttribute('class', 'card');
cardSymbol[i] = document.createElement('i');
cardSymbol[i].setAttribute('class', `fa fa-${symbols[i]}`);
card[i].appendChild(cardSymbol[i]);
cardDeck.appendChild(card[i]);
}
}
makeCards();
So int the array card I've stored all the cards, and added the cards in function makeCards , the problem is I want to add an Event Listener in another function to every single card, but if I iterate over the elements
with a for loop and I console.log() every element it shows me undefined, and this happens either I write the loop in a function or outside any function, but If I console.log(card) ; it shows me an array that contains all the elements of the array. Why I can't loop over them since I have an array?? Or should I add the eventListerns to elements when I create them in the function makeCards?????
You need a live event listener. If you are using jQuery you can use this
or if you are using native js, you can implement this
We can set one element that is a common ancestor to all card elements to listen for a "click" event occuring on it and/or its descendants. This is possible because of how an event bubbles. For details on this procedure read this article about Event Delegation.
The following Demo creates 2 arrays of matched FA classes and shuffles them. The ancestor element is created as deck and its descendant elements are card, and face elements which are created on each iteration of a for loop. Only the basic function of flipping is provided for each card/face, the logic for matching is beyond the scope of the OP question and requires a separate question to be posted.
Demo
Details are commented in Demo
/* Hardcode FA classes in symbol array
== Clone symbol array
== Use shuffle() function on both arrays
== Merge both arrays into faces array
*/
var symbol = ['fa-pied-piper-alt', 'fa-heart', 'fa-star', 'fa-star-o', 'fa-paw', 'fa-leaf', 'fa-cube', 'fa-cubes', 'fa-rebel', 'fa-empire'];
var match = symbol.slice(0);
var topCut = shuffle(symbol);
var bottomCut = shuffle(match);
var faces = topCut.concat(bottomCut);
// Create and reference parent element
var stack = document.createElement('main');
stack.id = 'deck';
// for each loop...
for (let c = 0; c < match.length * 2; c++) {
// Create a card element and add attributes
var card = document.createElement('a');
card.href = '#/';
card.classList.add.apply(card.classList, ['card', 'cover']);
/* Create a face element and add attributes
|| Note: each face is assigned a FA icon but not .fa class
*/
var face = document.createElement('i');
face.classList.add('face');
face.classList.add(faces[c]);
// Add each face to a card and each card to the deck (stack)
card.appendChild(face);
stack.appendChild(card);
}
// When complete, add deck to DOM
document.body.appendChild(stack);
// Reference deck
var deck = document.getElementById('deck');
/* Register deck to click event
|| When deck and/or its descendant elements are clicked...
|| invoke callback function flip()
*/
deck.addEventListener('click', flip, false);
// Pass Event Object
function flip(event) {
// Prevent <a> from jumping to a location
event.preventDefault();
/* event.target: origin of click event (clicked element)
|| event.currentTarget: element that listens for click (#deck)
|| if the clicked element is NOT #deck...
*/
if (event.target !== event.currentTarget) {
//...and if that clicked element is an <a>...
if (event.target.tagName === "A") {
/* toggle clicked <a> class .cover and
|| its child <i> class .fa on/off
*/
event.target.classList.toggle('cover');
var trump = event.target.firstElementChild;
trump.classList.toggle('fa');
}
}
}
// Utility function uses Fisher-Yates algorithm to shuffle arrays
function shuffle(array) {
var i = 0;
var j = 0;
var temp = null;
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
return array;
}
#deck {
display: flex;
flex-flow: row wrap;
width: 450px;
height: 300px;
border-radius: 6px;
border: 5px inset brown;
background: green;
}
.card {
text-decoration: none;
display: inline-block;
width: 48px;
height: 64px;
border-radius: 6px;
border: 3px solid #000;
background: #fff;
font-size: 40px;
text-align: center;
margin: 5px
}
.face {
transform: translateY(11px);
pointer-events: none;
color: inherit;
}
.cover {
color: transparent;
background: #fff;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
Fairly new to Javascript and trying a more complex script (to me, anyway).
The end-game for this script is the following:
Element tagged with onclick=(runscript) will prompt script to load a text file of site names/links, separated by commas.
Script loads text file into an array.
First loop iterates through array, separating the main array into two new arrays based on even/odd array position. (ex. Site name is 0, link is 1, name is 2, link is 3, etc.)
Second loop iterates through the site name array, creating a new div element for each value in the array.
Second loop also creates new anchor element, appending it to the div element.
Second loop sets div's class, anchor's href, and appends the new div to a container div.
I feel like I'm making a few noob mistakes and my lack of exposure to Javascript is keeping me from seeing them. I cut out the first two steps to test steps 3-6 instead.
This is what I've managed to come up with so far.. any nudge in the right direction would be awesome.
Thanks!
var main = ["Google", "http://google.com", 'Gmail', 'http://gmail.com', 'Hotmail', 'http://hotmail.com', 'Battle.net', 'http://battle.net', 'Steam', 'http://steampowered.com'];
function getSites() {
var site = new Array();
var link = new Array();
for (var i = 0; i <= main.length; i++) {
if (i % 2 == 0) {
link.push(main[i]);
} else {
site.push(main[i]);
}
}
for ($i = 1; i <= site.length; i++) {
var divElement = document.createElement("div");
var anchorElement = document.createElement("a");
divElement.appendChild(anchorElement);
divElement.className = "boxin";
anchorElement.href = link[i];
divElement.innerHTML = (site[i]);
linkContainer.appendChild(divElement);
}
}
getSites();
boxin {
height: 20px;
background-color: green;
}
#linkContainer div
{
border:solid 1px black;
margin:5px;
}
<div id="linkContainer"></div>
You have a bug in the second iteration, you are initializing a new variable $i, but the condition is checking for i<=site.length which will be false since the value of i is updated to main.length at the end of the first loop
But you really don't need to use 2 loop to solve the problem, you can use a single loop as below. Also you need to set the label text as the content of anchor element not of the div
var main = ["Google", "http://google.com", 'Gmail', 'http://gmail.com', 'Hotmail', 'http://hotmail.com', 'Battle.net', 'http://battle.net', 'Steam', 'http://steampowered.com'];
function getSites() {
for (var i = 0; i < main.length; i += 2) {
var divElement = document.createElement("div");
var anchorElement = document.createElement("a");
divElement.appendChild(anchorElement);
divElement.className = "boxin";
anchorElement.href = main[i + 1];
anchorElement.innerHTML = (main[i]);
linkContainer.appendChild(divElement);
}
}
getSites();
boxin {
height: 20px;
background-color: green;
}
#linkContainer div {
border: solid 1px black;
margin: 5px;
}
<div id="linkContainer"></div>
Do you really need them to be in an array? I think an object would work much better.
var sites = {
"Google": "http://google.co.uk",
"Gmail": "http://gmail.com"
};
Then you could loop through the object and achieve what you wanted.
Try it : i'm change your code little bit... below code 100% workable...
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="../js/jquery-1.7.1.min.js"></script>
<style type="text/css">
boxin {
height: 20px;
background-color: green;
}
#linkContainer div {
border: solid 1px black;
margin: 5px;
}
</style>
</head>
<body>
<div>
<div id="linkContainer"></div>
</div>
<script type="text/javascript">
var main = ["Google", "http://google.com", 'Gmail', 'http://gmail.com', 'Hotmail', 'http://hotmail.com', 'Battle.net', 'http://battle.net', 'Steam', 'http://steampowered.com'];
function getSites() {
var site = new Array();
var link = new Array();
for (var i = 0; i <= main.length; i++) {
if (i % 2 == 0) {
link.push(main[i]);
} else {
site.push(main[i]);
}
}
for (var i = 0; i < site.length; i++) {
var divElement = document.createElement("div");
var anchorElement = document.createElement("a");
divElement.appendChild(anchorElement);
divElement.className = "boxin";
anchorElement.href = link[i];
divElement.innerHTML = (site[i]);
document.getElementById("linkContainer").appendChild(divElement);
}
}
getSites();
</script>
</body>
</html>
I am looking to create a grid of 3x3 text input boxes, relative to an existing square div, using pure JavaScript. Preferably I would like to construct the grid of a single 1D array that cycles through every third box (if not, then an array of an array of input boxes would do - I hope this makes sense). This is what my code looks like at the moment, but only three of the boxes show when I cycle the array length (if I don't then the array extends linearly across beyond the div confines):
var row0 = new Array(9);
for (var i = 0; i < 9; ++i)
{
row0[i] = document.createElement('input');
row0[i].style.position = "absolute";
row0[i].type = "text";
row0[i].style.marginLeft = 35px *i % 105 + "px";
row0[i].style.width = "35px";
row0[i].style.height = "35px";
document.getElementById('block1').appendChild(row0[i]);
}
How can I get the grid to display correctly?
I would use a combination of javascript and CSS
DEMO http://jsfiddle.net/x8dSP/3010/
JS
window.onload = function () {
var parent_div = document.createElement("div")
parent_div.id = "parent"
document.body.appendChild(parent_div);
var x = 0;
while (x < 9) {
var child_input = document.createElement("input")
child_input.className = "child"
document.getElementById(parent_div.id).appendChild(child_input);
x++;
}
}
CSS
div {
width: 150px;
}
input {
display: inline-block;
width: 30px;
height: 30px;
margin: 5px;
}