I'm trying to generate a DIV table header row using the JavaScript (no jQuery) shown below but rather than the expected output shown here, what I generate is a row of the items in the array (the headings separated by commas).
var main = document.getElementById("left");
var likertTable = document.createElement("DIV"); //main table div
likertTable.setAttribute("class", "divTable");
var tableHeading = document.createElement("DIV"); // table heading
tableHeading.setAttribute("class", "divTableHeading");
var row = document.createElement("DIV");
row.setAttribute("class", "divTableRow");
tableHeading.appendChild(row);
likertTable.appendChild(tableHeading);
main.appendChild(likertTable);
var tableHeader = ["Question", "Strongly Agree", "Agree", "Undecided", "Disagree", "Strongly Disagree"];
for (var i = 0; i < tableHeader.length; i++) {
var tableCell = document.createElement("DIV");
tableCell.setAttribute("class","divTableCell");
row.appendChild(tableCell);
tableCell.innerHTML = tableHeader[i];
}
.divTable{
display: table;
width: 100%;
}
.divTableRow {
display: table-row;
}
/*.divTableHeading {
background-color: #EEE;
display: table-header-group;
}*/
.divTableCell, .divTableHead {
border: 1px solid #999999;
display: table-cell;
padding: 3px 10px;
}
.divTableHeading {
background-color: #EEE;
display: table-header-group;
font-weight: bold;
}
.divTableFoot {
background-color: #EEE;
display: table-footer-group;
font-weight: bold;
}
.divTableBody {
display: table-row-group;
}
<div id="left"></div>
The actual variable is var tableHeader = [ranges]; and it works just fine as seen in the screen capture and the snippet correctly appends if a regular HTML table is generated with a TH rather than DIV tag.
Where am I going wrong? Oh shoot!!! Asked an answered! var tableHeader = [ranges]; should have been var tableHeader = ranges;
Came home as the script ran perfectly in snippets editor.
Thanks StackOverflow.
var tableHeader = [ranges]; should have been var tableHeader = ranges; as the former placed the array in two pairs of square brackets without throwing an error in the console.
Related
I have a slider in my page and slider's indicators are dynamic, It bases on slider's elements' number and width of body.
My code block is:
function setIndicators(){
const indicator = document.createElement("div");
indicator.className = "indicator active";
indicatorContainer.innerHTML = "";
for(let i = 0;i <= maxIndex; i++){
indicatorContainer.appendChild(indicator.cloneNode(true));
}
updateIndicators();
}
which is working fine. But I want to show active indicator but I cannot manipulate elements' classes.
I tried this:
function updateIndicators(index) {
indicators.forEach((indicator) => {
indicator.classList.remove("active");
});
let newActiveIndicator = indicators[index];
newActiveIndicator.classList.add("active");
}
And I am not able to reach every indicators using index or anything I know/find. Also, it seems like NodeList not a HTML element.
Other things you may need:
const indicatorContainer = document.querySelector(".container-indicators");
const indicators = document.querySelectorAll(".indicator");
let maxScrollX = slider.scrollWidth - body.offsetWidth;
let baseSliderWidth = slider.offsetWidth;
let maxIndex = Math.ceil(maxScrollX / baseSliderWidth);
A better one I would suggest using the indicators in a different way. Since your HTML isn't shared, I have to assume a few things:
function clearAll() {
const activeOnes = document.querySelectorAll(".active");
activeOnes.forEach(function(activeOne) {
activeOne.classList.remove("active");
});
}
function chooseOne(index) {
clearAll();
const indicators = document.querySelectorAll(".indicator");
indicators[index].classList.add("active");
}
* {
font-family: 'Operator Mono', consolas, monospace;
}
.indicators {
border: 2px solid #ccc;
display: inline-block;
width: auto;
margin: 15px;
}
.indicators .indicator {
padding: 15px;
line-height: 1;
background-color: #fff;
flex-grow: 1;
text-align: center;
display: inline-block;
}
.indicator.active {
background-color: #f90;
}
<div class="indicators"><div class="indicator">I1</div><div class="indicator">I2</div><div class="indicator">I3</div><div class="indicator">I4</div><div class="indicator">I5</div></div>
<button onclick="chooseOne(2); return false">Select I3</button>
<button onclick="chooseOne(3); return false">Select I4</button>
I would have done this differently this way.
Preview
Why can't character.setAttribute() work. If you delete the line, the
format of what I am trying to accomplish is there, but the CSS for the letters don't make it invisible. If I do put the setAttribute() in, the code doesn't work.
<!Doctype html>
<html lang="en">
<head>
<style>
.hidden {
visibility: hidden;
}
ul {
display: inline;
list-style-type: none;
}
.boxes {
font-size:1.6em;
text-align:center;
width: 10px;
border-bottom: 3px solid black;
margin: 5px;
padding: 10px;
display: inline;
}
</style>
</head>
<body>
<script>
var possibleWord = ["cow", "better", "harder", "justify", "condemn",
"control", "hello", "understand", "life", "insight","date", "righteous"];
var hangmanWord = possibleWord[Math.floor(Math.random() *
possibleWord.length)];
var underlineHelp;
var space;
var guess;
var guesses = [];
var placement;
var underscores;
var character = [];
window.onload = function () {
placement = document.getElementById('hold');
underlineHelp = document.createElement('ul');
placement.appendChild(underlineHelp);
for (i = 0; i < hangmanWord.length; i++) {
underscores = document.createElement('li');
underscores.setAttribute('class', 'boxes');
guesses.push(underscores);
underlineHelp.appendChild(underscores);
character = document.createElement('li');
character = document.createTextNode(hangmanWord[i]);
character.setAttribute('class', 'hidden');//The issue is here, if you take
//this line out then the format will be correct, except I am trying to hide
//the letters with the css attribute "hidden."The dashes are represented by
//the bottom-border of "boxes."
underscores.appendChild(character);
}
</script>
<div id = "hold"></div>
</html>
A TextNode doesn't have attributes.
character = document.createElement('li');
character = document.createTextNode(hangmanWord[i]);
I am guessing you want to do:
character = document.createElement('span');
character.appendChild(document.createTextNode(hangmanWord[i]));
character.classList.add('hidden');
underscores.appendChild(character);
Working example:
var possibleWord = ["cow", "better", "harder", "justify", "condemn",
"control", "hello", "understand", "life", "insight", "date", "righteous"
];
var hangmanWord = possibleWord[Math.floor(Math.random() *
possibleWord.length)];
var underlineHelp;
var space;
var guess;
var guesses = [];
var placement;
var underscores;
var character = [];
window.onload = function() {
placement = document.getElementById('hold');
underlineHelp = document.createElement('ul');
placement.appendChild(underlineHelp);
for (i = 0; i < hangmanWord.length; i++) {
underscores = document.createElement('li');
underscores.setAttribute('class', 'boxes');
guesses.push(underscores);
underlineHelp.appendChild(underscores);
character = document.createElement('span');
character.appendChild(document.createTextNode(hangmanWord[i]));
character.classList.add('hidden');
underscores.appendChild(character);
}
}
.hidden {
visibility: hidden;
}
ul {
display: inline;
list-style-type: none;
}
.boxes {
font-size: 1.6em;
text-align: center;
width: 10px;
border-bottom: 3px solid black;
margin: 5px;
padding: 10px;
display: inline;
}
<div id="hold"></div>
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);
});
I have four tables of soccer players, one for goalkeepers, one for defenders, one for midfielders and one for attackers. I want the user to be able to change the position of a player so that he'll disappear from his current table and appear in another one without a page refresh.
The only method that I can think of is to have each player listed in all four tables but have him hidden for three of them. Then if he changes, I hide him in the current table and show him in another one.
I know how to achieve this, but it seems a bit heavy and I'm wondering if there's a more elegant solution.
You can use appendChild() in pure JavaScript to move a node from one place to another. The node is automatically removed from its old position in the DOM.
To quote the Mozilla Developer Network documentation on appendChild:
If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position (there is no requirement to remove the node from its parent node before appending it to some other node).
This means that a node can't be in two points of the document simultaneously. So if the node already has a parent, it is first removed, then appended at the new position.
The following snippet demonstrates the use of appendChild() to move rows between tables. Click on the move buttons to move an item from one table to the other.
window.onload = function () {
var data = {
like: ['vanilla', 'pistachio', 'squirrels', 'squash', 'mountains'],
dislike: ['chocolate', 'trucks', 'football', 'hard candy', 'valleys']
};
var tables = {};
var moveMe = function () {
this.table = tables[this.table === tables.like ? 'dislike' : 'like'];
this.table.tbody.appendChild(this.tr);
};
Object.keys(data).forEach(function (key) {
var container = document.createElement('div'),
table = tables[key] = document.createElement('table'),
tbody = table.tbody = document.createElement('tbody');
data[key].forEach(function (item) {
var tr = document.createElement('tr'),
td = document.createElement('td');
td.innerHTML = item;
tr.appendChild(td);
tbody.appendChild(tr);
var button = document.createElement('button');
button.innerHTML = 'move';
button.onclick = moveMe;
button.table = table;
button.tr = tr;
td.appendChild(button);
});
table.appendChild(tbody);
var header = document.createElement('h2');
header.innerHTML = key;
container.appendChild(header);
container.appendChild(table);
container.className = 'container';
document.getElementById('wrapper').appendChild(container);
});
};
* {
box-model: border-box;
}
body {
font-family: sans-serif;
}
#wrapper {
width: 450px;
}
.container {
display: inline-block;
width: 200px;
padding: 10px;
}
h2 {
margin: 5px 0;
color: #666;
}
table {
width: 200px;
border-collapse: collapse;
}
td {
color: #333;
padding: 10px;
border: 1px solid #bbb;
position: relative;
}
td button {
position: absolute;
right: 5px;
top: 5px;
border: 2px solid #ccc;
border-radius: 5px;
background: #fff;
font-size: 12px;
}
td button:hover {
outline: none;
border-color: #888;
cursor: pointer;
}
<div id="wrapper"></div>
You could also use table api to manipulate your tables, here is a sample:
moving 1,1,1 element to 3,1,1
var tables = document.querySelectorAll("table")
var elementToMove = tables[0].rows[0].cells[0]
var destination = tables[2].rows[0].cells[0]
destination.innerHTML = elementToMove.innerHTML
elementToMove.innerHTML = ""
<table>
<tr>
<td>1,1,1</td>
<td>1,1,2</td>
<td>1,1,3</td>
</tr>
<tr>
<td>1,2,1</td>
<td>1,2,2</td>
<td>1,2,3</td>
</tr>
<tr>
<td>1,3,1</td>
<td>1,3,2</td>
<td>1,3,3</td>
</tr>
</table>
<br>
<table>
<tr>
<td>2,1,1</td>
<td>2,1,2</td>
<td>2,1,3</td>
</tr>
<tr>
<td>2,2,1</td>
<td>2,2,2</td>
<td>2,2,3</td>
</tr>
<tr>
<td>2,3,1</td>
<td>2,3,2</td>
<td>2,3,3</td>
</tr>
</table>
<br>
<table>
<tr>
<td>3,1,1</td>
<td>3,1,2</td>
<td>3,1,3</td>
</tr>
<tr>
<td>3,2,1</td>
<td>3,2,2</td>
<td>3,2,3</td>
</tr>
<tr>
<td>3,3,1</td>
<td>3,3,2</td>
<td>3,3,3</td>
</tr>
</table>
Note that i'm using innerHTML to access data, but you could identify whatever element you have in the cell and then use the appendChild method to move the element you need
For some reason, the input I created with the table is NOT AS LONG. I used normalize.css too, and all that did is made it slightly longer. I need it to fill the page and I have no idea where to even begin wording my google searches for such an issue.
Also, all of the css rules DO apply except for width (i think). My dynamically created input is just not as long as the others. Blows my mind.
function makeInput() {
var myInput = document.createElement("input");
myInput.type = "text";
myInput.value = "Here is where the quetsion goes";
return myInput;
}
function makeTable() { // make table with one row and one td
var myTable = document.createElement('table'); // Create table called myTable
var myRow = document.createElement('tr'); // create row called myTr
myTable.id = "myTalbe"
myTable.border = "0"
myTable.cellspacing = "2"
myTable.cellpadding = "0"
myTable.width = "100%"
myTable.type = "text"
var td1 = document.createElement('td'); // td1 for input
var td2 = document.createElement('td'); // td2 for button
var text1 = document.createTextNode('Here is my text');
td1.appendChild(makeInput()); // append makeInput();
td2.appendChild(makeButton()); // append my input form to td1
myRow.appendChild(td1);
myRow.appendChild(td2); // append td1 element to my table
myTable.appendChild(myRow); //
document.body.appendChild(myTable);
}
Game plan: makeInput() returns an input element. makeTable() puts it inside a <td>. makeTable() runs under $(document).ready (jQuery).
I have 5 other inputs on the page. All of which are managed by this:
input[type="text"] {
height: 30px;
display: block;
margin: 0;
width: 98%;
font-family: sans-serif;
font-size: 18px;
appearance: none;
box-shadow: none;
border-radius: none;
}
table tr td input[type="text"] {
height: 30px;
display: block;
margin: 0;
width: 98% !important;
font-family: sans-serif;
font-size: 18px;
appearance: none;
box-shadow: none;
border-radius: none;
}
You try this css....
Tables come with spacing between cells, borders, and padding on cells. Reset those to 0 and it should fill the available space, matching the other inputs. Since there is a cell next to the inputs they will not be the exact same width, since the other cell pushes it to be narrower, but they will line up at least.
function makeInput() {
var myInput = document.createElement("input");
myInput.type = "text";
myInput.value = "Here is where the quetsion goes";
return myInput;
}
function makeTable() { // make table with one row and one td
console.log("Make a table");
var myTable = document.createElement('table'); // Create table called myTable
var myRow = document.createElement('tr'); // create row called myTr
myTable.id = "myTalbe"
myTable.border = "0"
myTable.cellspacing = "2"
myTable.cellpadding = "0"
myTable.width = "100%"
myTable.type = "text"
var td1 = document.createElement('td'); // td1 for input
var td2 = document.createElement('td'); // td2 for button
var text1 = document.createTextNode('Here is my text');
td1.appendChild(makeInput()); // append makeInput() to td1
td2.appendChild(makeButton()); // append makeButton() to td2
myRow.appendChild(td1); // append td1 to the row
myRow.appendChild(td2); // append td2 to the row
myTable.appendChild(myRow); // append the row to the table
document.body.appendChild(myTable); // append the table to the body
}
function makeButton() {
var myButton = document.createElement('button');
var txt = document.createTextNode('Test');
myButton.appendChild(txt);
return myButton;
}
$(document).ready(makeTable);
button, input[type="text"] {
width: 100%;
box-sizing: border-box;
height: 30px;
line-height: 30px;
font-family: sans-serif;
font-size: 18px;
}
input[type="text"] {
display: block;
margin: 0;
appearance: none;
box-shadow: none;
border-radius: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
td {
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="Made on load" />
<input type="text" value="This one was made on load too" />