Line up generated divs horizontally - javascript

I'm creating a map generator that lets a user enter the number of rows and columns in the map, and then create that map (as divs). Everything works correctly, except the divs, instead of being in rows and columns, it's all in one big column. It does have the correct amount of tiles (for example, it has 6 if you enter 3 and 2, or 25 if you enter 5 and 5). The kicker is that if I enter divs in the regular html file, they line up like they're supposed to.
Here's my javascript function:
function createMap(rows, columns) {
var $div = $('<div></div>');
var k = 0;
while (k < rows) {
for (i = 0; i < columns; i++) {
$div.append('<div></div>');
}
$div.append('<br>');
k++;
}
$('body').empty();
$('body').append($div);
}
Here's my CSS:
div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
}
The generated divs are reading the CSS fine - they have the proper height, width, and border. It seems that they're just creating a new line for every one. Can anyone tell me why?

You gave ALL your divs a width of 100px. You have divs in a div. So you need to change your styles to only target the children
You want only the children divs to have the width of 100px.
function createMap(rows, columns) {
var $div = $('<div></div>');
var k = 0;
while (k < rows) {
for (i = 0; i < columns; i++) {
$div.append('<div></div>');
}
$div.append('<br>');
k++;
}
$('body').empty();
$('body').append($div);
}
createMap(2,3)
div > div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Float your divs
div {
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
float: left;
}

Related

Keydown function runs before character is printed to screen?

I have an element that sits above 3 elements with the same class. When I type into one of the content editable divs, it expands the element if the width goes beyond its original. I want to set the above element to equal the same width as the other 3.The issue I am running into is that when I run the keydown() function, it runs before the actual character is printed to the screen, thus the width is always one character too large, or small. If I run the keyup() function then it is delayed and is clunky because the character is printed to the screen before my finger unpresses the key. How do I remedy this? Is there a way to run the function when the key is printed?
$(".tr1").keydown(function() {
var elements = document.getElementsByClassName('tr1');
var totalWidth = 0;
for (var i = 0; i < elements.length; i++) {
totalWidth += elements[i].offsetWidth;
}
document.getElementById("qa-checklist").style.width=''+totalWidth+'px';
});
I added a stackblitz:
https://js-ic8uy7.stackblitz.io
The oninput event seems to not have this issue.
<label for="test">Using oninput:</label>
<input type="text" id="test" oninput="console.log(this.value)"></input>
EDIT: To do this in your example, replace "keydown" with "input":
document.addEventListener('input', function(event) {
console.log("change");
var elements = document.getElementsByClassName('tr1');
var totalWidth = 0;
for (var i = 0; i < elements.length; i++) {
totalWidth += elements[i].offsetWidth;
}
console.log(totalWidth);
document.getElementById("qa-checklist").style.width=''+totalWidth+'px';
});
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
.rowcell {
outline: grey;
border: 1px solid black;
min-width: 50px;
}
#qa-checklist {
display: inline-block;
width: 1px;
border-bottom: 50px solid black;
}
<div id="qa-checklist"></div>
<div style="display:flex;">
<div class="rowcell tr1" contenteditable="true"></div>
<div class="rowcell tr1" contenteditable="true"></div>
<div class="rowcell tr1" contenteditable="true"></div>
</div>

Is there a way to check the bottom of a child div?

I'm trying to implement an Infinity scroll.
But not a window object, the target is a child div with a scroller.
Is there a way to examine the current height of a child div with JavaScript?
For example, I would like to request an event when the scroll touches at the end.
This is my template code.
<div
style="overflow-y: scroll; height:500px;"
class="scroll-content"
#scroll="onScroll"
>
Here is an example:
var listElm = document.querySelector('#infinite-list');
// Add items.
var nextItem = 1;
var loadMore = function() {
for (var i = 0; i < 10; i++) {
var item = document.createElement('li');
item.innerText = 'Item ' + nextItem++;
listElm.appendChild(item);
}
}
// Detect when scrolled to bottom.
listElm.addEventListener('scroll', function() {
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
loadMore();
}
});
// Initially load some items.
loadMore();
#infinite-list {
/* We need to limit the height and show a scrollbar */
width: 200px;
height: 100px;
overflow: auto;
/* Optional, only to check that it works with margin/padding */
margin: 30px;
padding: 20px;
border: 10px solid black;
}
/* Optional eye candy below: */
li {
padding: 10px;
list-style-type: none;
}
li:hover {
background: #ccc;
}
<ul id='infinite-list'>
</ul>
The following function returns, whether the user has scrolled to the bottom of a certain element:
function scrollEnd(el) {
return (el.scrollTop + el.offsetHeight >= el.scrollHeight);
}
If you add this to a scroll event listener:
element.addEventListener('scroll', () => {
if (scrollEnd(element)) {
// the user reached the end
}
})
I tried this on a textarea, should work with anything, though.

How to display row number next to each row on contenteditable div

I have a contenteditable div and I want the site to count each row of text the user has in the div similar to many coding IDEs. (Example image below to show what I mean:)
How would I go about doing this?
You can accomplish this with two container elements and a little bit of scripting:
$(document).ready(function(){
$('#edit').css('min-height', $('#edit').height());
$('#edit').html('');
var currentHeight = $('#edit').height();
var lineHeight = currentHeight;
$('#edit').keyup(function(){
if($(this).height()!=currentHeight){
currentHeight = $(this).height();
var lines = currentHeight/lineHeight;
$('#nums').html('')
for (i = 1; i < lines+1; i++) {
$('#nums').append('<span>'+i+'</span>')
}
}
});
});
#container{
border: 2px solid gray;
display: flex;
width: 200px;
}
#nums{
width: 25px;
background-color: lightgrey;
}
#nums span{
width: 100%;
display: block;
text-align: center;
}
#edit{
display: inline-block;
width: 100%;
}
#editwrapper{
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="nums">
<span>1</span>
</div>
<div id="editwrapper">
<div id="edit" contenteditable="true">
filler
</div>
</div>
</div>
That's not so simple, actually. If a user typed in your div and the text wrapped, JavaScript doesn't know that it wrapped; there's no row to count!
This solution is super specific, and I'll leave showing the line numbers to you:
<div contenteditable="true" id="myDiv" style="width:300px;font-family:monospace" onchange="myHandler()"></div>
<script>
const limit = 40 // number of monospace chars to fill a row
let count = 0
function myHandler (e) {
let lines = Math.ceil(e.target.value.length / limit)
if (lines !== count) {
showlines(lines) // your function to display the line #s
count = lines
}
}
</script>
Takeaway: your div should be a fixed width and you should count how many monospace chars fit within that width. Then display those lines.

Displaying divs when the ones before are full with JQuery

I would like to display divs when the div contents before is full of words and continue to fill this new div with the rest of the words.
I don't know how to do it. In fact, in the code below I wrote that the div is displayed on click of a button. I also can't set the "fill-action" explained above.
The limit of the words in one div has to be settable from the code.
For example, if I set the limit to two words and there are only two words to be displayed, the second div shouldn't be created.
But If there are four words to be displayed and the limit is still on two words,
the second div has to be created and has to be filled with the third and fourth words.
Another problem is that if I write HTML text (e.g. <font color="#ff0000">), the tags (e.g. <font) shouldn't be considered as a word.
Jsfiddle
HTML:
<div id="faketxt" contenteditable>Write Here</div>
<button id='btn'>OK</button>
<div id='casella' class='fakes'></div>
CSS:
#faketxt {
-moz-appearance: textfield-multiline;
-webkit-appearance: textarea;
border: 1px solid gray;
height: 28px;
overflow: auto;
padding: 2px;
resize: both;
width: 400px;
}
#casella{
width: 150px;
height: 300px;
font-size: 10px;
border-style: solid;
}
.fakes{
width: 150px;
height: 300px;
font-size: 10px;
border-style: solid;
}
JQUERY:
$('#btn').click(function() {
var primo = document.getElementById('faketxt');
var secondo = document.getElementById('casella');
secondo.innerHTML = primo.innerHTML;
var myDiv = $('#casella');
myDiv.text(myDiv.text().substring(0,5)) //This is when the div is "full"
});
document.getElementById("btn").onclick = function () {
var ok = true;
if (ok === true) {
var div = document.createElement('div');
div.className = 'fakes';
document.getElementsByTagName('body')[0].appendChild(div);
}
};
In this case I set that the div is full when there are 5 letters, so the word "Here" has to be displayed in the second div...
Is this possible?
I can't figure it out.
for displaying divs at right position
css:
.fakes{
width: 150px;
height: 300px;
font-size: 10px;
border-style: solid;
display : inline-block;
}
#boxes{
display : flex;
}
HTML
<div id="faketxt" contenteditable>Write Here</div>
<button id='btn'>OK</button><br>
<div id="boxes">
<div id='casella' class='fakes'></div>
</div>
Use String.split() to separate the words (by spaces) and add a div container for each word using Array.foreach(). Also with this approach, use Array.shift() to set the text of the myDiv element (i.e. with id="casella") to the first word.
UPDATE:
Per the changing requirements, the code below now has a number input for the word limit. It then strips HTML codes (using the HTML entities) using a regular expression and then uses a counter to add words to newly created div elements. The functionality to create a new div element has been abstracted to the function createdDiv().
$('#btn').click(function() {
var primo = document.getElementById('faketxt');
var wordLimit = $('#wordLimit').val();
//strip html characters from string and use a regular expression
//to split based on white-space characters
var words = primo.innerHTML.replace(/(<([^>]+)>)/ig,"").split(/\s/);
if (words.length) {
var count = 0;
var div = createDiv();
words.forEach(function(word) {
if (++count > wordLimit) {
count = 0; //reset counter
div = createDiv();
}
if (div.innerHTML) {
div.append(' ');
}
div.append(word);
});
}
});
function createDiv() {
div = document.createElement('div'); //could use jQuery $('div') instead
div.className = 'fakes';
document.body.append(div);
return div;
}
#faketxt {
-moz-appearance: textfield-multiline;
-webkit-appearance: textarea;
border: 1px solid gray;
height: 28px;
overflow: auto;
padding: 2px;
resize: both;
width: 400px;
}
#casella {
width: 150px;
height: 300px;
font-size: 10px;
border-style: solid;
}
.fakes {
width: 150px;
height: 300px;
font-size: 10px;
border-style: solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Word Limit:
<input type="number" id="wordLimit" value="1" />
</div>
<div id="faketxt" contenteditable>Write Here</div>
<button id='btn'>OK</button>
var myDiv = $('#casella');
var primo = document.getElementById('faketxt');
var secondo = document.getElementById('casella');
$('#btn').click(function() {
var inputArray = primo.innerHTML.split(" ");
var secDivContent = '';
if(inputArray[0].length > 5 || primo.innerHTML.length > 5 ) {
secDivContent = primo.innerHTML.substr(5);
}
var div = document.createElement('div');
div.className = 'fakes';
div.innerHTML = secDivContent;
document.getElementsByTagName('body')[0].appendChild(div);
});

javascript chatbox / messenger script

I'm trying to write a facebook like chatbox, but i've encountered a small problem.
I'm using the following code (it's only test code, so it's not really clean):
css code:
#messenger {
position: fixed;
bottom: 0px;
right: 10px;
width: 200px;
height: 300px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
#messenger.p {
text-align: right;
}
#contacts {
margin: 5px 5px 5px 5px;
}
#chatspace {
position: fixed;
bottom: 0px;
right: 240px;
height: 20px;
left: 20px;
background-color: #ECECEC;
border: 1px solid #000;
z-index: 4;
}
.chatbox {
position: absolute;
bottom: 0px;
width: 200px;
height: 200px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
html/javascript code:
<script type="text/javascript">
var i = 0;
function oc_chatbox() {
if (i == 0) {
document.getElementById('contacts').style.visibility = 'hidden';
document.getElementById('messenger').style.height = '20px';
i = 1;
}
else {
document.getElementById('contacts').style.visibility = 'visible';
document.getElementById('messenger').style.height = '300px';
i = 0;
}
}
function new_chat(userid) {
var new_right;
new_right = document.getElementById('messenger').style.right;
//alert('old value: '+ new_right);
new_right += 20;
//alert('New value of right: '+ new_right);
document.getElementById('chatspace').innerHTML = '<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>';
//document.write('<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>');
}
</script>
<div id="chatspace"></div>
<div id="messenger">
<p>Collapse</p>
<div id="contacts">
<ul>
<li>contact A</li>
</ul>
</div>
</div>
the problem is, that when I try to add new chats to the chatbar, i can't seem the place them next to each other.
anyone who can help ?
EDIT:
so i changed to javascript code to:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 10;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = document.body.clientWidth-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox shadow";
newChat.style.right = new_right+"px";
newChat.innerHTML = '<p>'+userid+'</p><p><textarea></textarea></p>';
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
and now it works, thanks !
You cannot get an element right offset using its style, unlest the style is set and valid. Instead you must get element.offsetLeft and size of window area and do this:
new_right = windowSize()[0]-messenger.offsetLeft;
Where window size is this function.
Here is my, working, version of your function:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 20;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = windowSize()[0]-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox";
newChat.style.right = new_right+"px";
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
You may get errors if console is not defined in your brouwser. But in such case you should take a better browser. Normally, the if(console!=null) is put in code.
And here is the link.
You should try adding a float style.
.chatbox {
float: right;
}
Add that to your chatbox styles. You may need to mess around a bit to make sure the float doesn't mess with your other elements. You may need a better container for them.
If you want to get really fun, you can add .draggable() from jQuery, and you can have them snap to your chat bar. You can then change the order of your chats.

Categories