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.
Related
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)
My code isnt working and I am getting an "Uncaught TypeError: Cannot read property 'getElementByTagName' of null at HTMLButtonElement.countInParagraphs at line 76.
can you help me figure out my problem.
Im thinking new eyes can figure out the problem better than I can.
Thank you
<!DOCTYPE html>
<html>
<head>
<title>Word Count Version 2</title>
<style>
button{
margin: 1em;
}
#leftArea{
width: 35%;
float: left;
height: 500px;
background-color: #C200AF;
padding: 10px;
}
#rightArea{
width: 30%;
float: left;
height: 500px;
background-color: #C2AF00;
padding: 10px;
}
#midArea{
width: 30%;
float: left;
height: 500px;
background-color: #00C2AF;
padding: 10px;
}
h3{
margin-left: 10px;
}
#paragraphs > p{
background-color: #66ffff;
}
</style>
<script>
"use strict;"
function buildParagraphs()
{
var sentenceArea = document.getElementById("sentence");
var words = sentenceArea.value;
if(words.length == 0)
{
return;
}
var wordsArray = words.split(" ");
//Get the div element with id = paragraphs and assign it to a variable called midDiv
var midDiv = document.getElementById("paragraphs");
for(var i = 0; i < wordsArray.length; i++)
{
//Build the p elements
//create a new p element and store it in a variable called newPara
var newPara = document.createElement("p");
//create a new text node from the current item in the wordsArray and store it in a variable called textNode
var textNode = document.createTextNode(wordsArray[i]);
//Append the text node to the newPara you just created
newPara.appendChild(textNode);
//Append the newPara element to the midDiv element
midDiv.appendChild(newPara);
}
sentenceArea.value = "";
}
function countInParagraphs()
{
var textArea = document.getElementById("searchWord");
var searchWord = textArea.value;
//Get the div element with id = paragraphs and assign it to a variable called midDiv
var midDiv = document.getElementById("wordList");
//Declare a variable called paraElements and assign all of the paragraph (p) tags from the midDiv element to it.
---> LINE 76 var paraElements = midDiv.getElementsByTagName("p");
var count = 0;
//Start a for-loop that sets a variable i to 0; checks it against the length of the paraElements array; and increments i by 1
for (var i =0; i <paraElements.length; i++)
{
//Write an if-statement that checks the innerHTML of the current paragraph element
if (searchWord == paraElements[i].innerHTML)
{
count++
}
//against the searchWord variable to see if they are the same. If they are, add 1 to the count.
}//end for
//Get the element with id = word and assign it to a variable called wordArea
var wordArea = document.getElementById("word");
//Assign the searchWord to the innerHTML of wordArea
wordArea.innerHTML = searchWord;
//Get the element with id = wordCount and assign it to a variable called countArea
var countArea = document.getElementById("wordCount");
//Assign the count to the innerHTML of countArea
count.innerHTML = countArea;
textArea.value = "";
}
window.onload = function()
{
var buildBtn = document.getElementById("buildBtn");
buildBtn.onclick = buildParagraphs;
var countBtn = document.getElementById("countBtn");
countBtn.onclick = countInParagraphs;
}
</script>
</head>
<body>
<div id = "leftArea">
<div>
Enter a sentence:
<textarea id = "sentence" rows = "10" cols = "30"></textarea>
</div>
<div>
<button type="button" id = "buildBtn">Build paragraphs</button>
</div>
<div>
Enter a word to find in the paragraphs:
<input type="text" id = "searchWord">
</div>
<div>
<button type="button" id = "countBtn">Count in paragraphs</button>
</div>
</div>
<div id = "midArea">
<h3>Word list</h3>
<div id = "paragraphs">
</div>
</div>
<div id = "rightArea">
The number of times the word '<span id = "word"></span>' turns up in the sentence is: <span id = "wordCount"></span>
</div>
</body>
Try moving your script to the end of your HTML document, right before </body> so that it looks like so: <script>...</script></body>.
I believe null means the element does not exist yet in the DOM, as opposed to undefined which means it's in the DOM, so it can be found, but is undefined.
If your script executes before the rest of your HTML document loads, you'll usually end up getting null and perhaps sometimes undefined errors.
As there is no element with id 'wordList', this throws an error. But there is an element with id 'word'. So you can replace id to var midDiv = document.getElementById("word"); in line number 74.
First of all you don't have the element with id == wordList at the page. But try to change string 76 to the code:
var paraElements = [];
if (midDiv) {
paraElements = midDiv.getElementsByTagName("p");
}
Goal is to create a image-carousel with 7 images in a row.
I'm reading data from a json-file. This all works fine.
What I do not get working is a loop that separates groups of 7 images in separate as per example below. Any advice is greatly appreciated for this jQuery-beginner.
<div class='active item'>
Image-1
Image-2
Image-3
Image-4
Image-5
Image-6
Image-7
</div>
<div class='item'>
Image-8
Image-9
Image-10
I tried with two things:
insertBefore
$.each(data.items, function(index, element) {
var myString = $('<div></div>');
if (index % 7 == 0) {
$("<p>Test</p>").insertBefore(".span2");
}
myString.append($('<div class="span2">')
.append($("<a href=" + index + " class='thumbnail'>"))
.append("<img src=http://0.0.0.0:3000/images/col/tn/" + element.imgf + " alt='Image' style='max-width:100%;'/>")));
myString.appendTo('#show-carousel');
if /else
$.each(data.items, function(index, element){
var myString = $('<div></div > ');
if (index % 7 == 0) {
myString.append("<div class='item'>");
myString.append($("<div class='row-fluid'>")
.append($(' < div class="span2"> ')
.append($("<a href="+index+" class='thumbnail'>")
.append("<img src=http://0.0.0.0:3000/images/col/tn/"+element.imgf+" alt='Image' style='max-width: 100%;'/>"))));
}
else {
myString.append($('<div class="span2">')
.append($("<a href="+index+" class='thumbnail'>")
.append("<img src=http://0.0.0.0:3000/images/col/tn/"+element.imgf+" alt='Image' style='max-width: 100%;'/>")));
}
myString.appendTo('#show-carousel');
You can extract the functionality of executing a callback for a certain portion of an array into a helper function.
// function that executes a callback for a portion of an array
function forEachArrayGroup(arr, start, end, fn) {
if (end > arr.length) end = arr.length; // normalize for out of bounds
for (let i = start; i < end; i++) {
fn(arr[i], i);
}
}
This would allow you to separate the logic of splitting data into portions from adding data to the DOM:
for (let i = 0; i < items.length; i += 7) {
// we create an item that will hold the portion
const $item = $('<div class="item"></div>');
// append the group to the current item
forEachArrayPortion(items, i, i + 7, function(dataItem, index) {
// this executes for each item in the group
const $imgWrapper = // create the a, img and rest
$item.append($imgWrapper);
});
}
Here's a full example:
const data = { items: Array.from({ length: 18 }, (_, i) => i).map(() => ({ imgf: 'i_am_fake' })) };
function forEachArrayGroup(arr, start, end, fn) {
if (end > arr.length) end = arr.length; // normalize for out of bounds
for (let i = start; i < end; i++) {
fn(arr[i], i);
}
}
function displayItemsInGroups(items, groupSize) {
for (let i = 0; i < items.length; i += groupSize) {
// this executes for each group of `partSize` number of items
// we create an item that will hold the group
const $groupItem = $('<div class="item"></div>');
// make sure the first item is active
if (i === 0) {
$groupItem.addClass('active');
}
// create the row that will contain the image groups
const $groupRow = $("<div class='row-fluid'>");
// add group row to the current item
$groupRow.appendTo($groupItem);
// add current item to the carousel
$groupItem.appendTo('#show-carousel');
// append the group to the current row
forEachArrayGroup(items, i, i + groupSize, function(dataItem, index) {
// this executes for each item in the group
const $imgWrapper = $('<div class="span2">')
.append($("<a href=" + index + " class='thumbnail'>")
// fake image
.append("<div class="+dataItem.imgf+">Image "+(index+1)+"</div>"));
$groupRow.append($imgWrapper);
});
}
}
displayItemsInGroups(data.items, 7);
.item {
padding: 10px;
border: 1px solid #aaa;
margin-bottom: 1px;
}
.item.active {
border-color: #018bbc;
background-color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="show-carousel"></div>
If I understand you correctly, you are trying to separate the images in groups of 7. To do this, you are on the correct path by using Modulus.
I would test to see when your loop index mod seven equals zero and then append a div group. Check out the code below.
var $carousel = $('#show-carousel'),
$item,
myArr = [],
i;
// populate our array with some fake data.
for (i = 0; i < 15; i++) {
var imgInfo = {
imgf: 'image' + (i + 1) + '.jpg'
};
myArr.push(imgInfo);
}
// loop through the array and add your items to your element
$.each(myArr, function(index, obj) {
if (index % 7 === 0) {
// create a div that will hold your images
$item = $('<div class="item"></div>');
// append this div to our carousel element
$carousel.append($item);
}
// $item is a reference to the last created div
$item.append('<div class="span2"><img src="http://0.0.0.0:3000/images/col/tn/' + obj.imgf + '" alt="Image" style="max-width:100%;"></div>');
});
$('.item:eq(0)').addClass('active');
#show-carousel .item {
display: none;
padding: 5px;
margin: 5px;
border: 1px solid red;
}
#show-carousel .item.active {
display: block;
}
#show-carousel .item .span2 {
display: inline-block;
width: 50px;
height: 50px;
padding: 5px;
margin: 5px;
border: 1px solid grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="show-carousel"></div>
*edit: updated code to better reflect what you had in your example.
So I am creating a platformer game with jQuery, JavaScript and HTML. I would like to make every level with an array containing numbers. Each number will then be a "block" of the platformer.
For instance:
var level = ["10101"];
Would create 3 different blocks, each of with are seperated by a blank space.
However, in the platformer, every number of the array caracterises the height, so a 2 would be on top of a 1.
See where I'm going?
Thing is, I have no clue how to append a series of div's to the game so that they have diffrent x position to fill the .game div.
Plus, I added a for loop with a variable named j, however, if I take out anything to do with jand the loop itself, the code doesn't work... why?
I have the code on CodePen, but here is what I have done so far anyway (for some reason it doesn't work on stackoverflow):
IMPORTANT: The CodePen uses SCSS, not CSS, I converted the code using SassMeister !
$(document).ready(function() {
var level = ["1112222111111111111"];
for (var i = 0; i < level.length; i++) {
for (var j = 0; j < level[i].length; j++) {
var n = level[i][j];
var s = $(".block").width();
if (n === "1") {
$("<div>", {
"class": "block pos1" //or any other logic applied to your borad
}).appendTo(".game");
$(this).css("left", i * s + "px")
}
if (n === "2") {
$("<div>", {
"class": "block pos2" //or any other logic applied to your borad
}).appendTo(".game");
}
}
}
});
.game {
position: absolute;
left: calc((100% - 800px)/2);
height: 500px;
width: 800px;
border: 2px solid black;
}
.block {
background-color: black;
height: 50px;
width: 50px;
position: absolute;
border: 0.5px solid red;
}
.pos1 {
bottom: 0;
}
.pos2 {
bottom: 50px;
}
.pos3 {
bottom: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
<!-- examples of positions -->
<!--<div class = "block pos1"></div>
<div class = "block pos2"></div>
<div class = "block pos5"></div>
<div class = "block pos4"></div>-->
</div>
Please Help!
Thank you! Tell me if I need to be more clear!
To append the element using jQuery, replace
for(var each in level) {
level[each].$(".game").append("<div class = 'block pos3'></div>");
}
with
for(var i = 0, length = level.length; i < length; i++){
$("<div>", {
"class": "block pos" + level[i] //or any other logic applied to your borad
}).appendTo(".game");
}
Also, for(var i in obj) is for iterating through the properties of an object, the sequence of the element being iterated is not guaranteed. For arrays, you should use for(var i = 0; i < x; i++) Javascript for loop
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>