So below I have the HTML code that is part of my draggable/droppable:
Drag from here:
<ul id="sortable1" class="dropBox connectedSortable">
<li class="ui-state-default">Word 1</li>
<li class="ui-state-default">Word 2</li>
<li class="ui-state-default">Word 3</li>
<li class="ui-state-default">Word 4</li>
</ul>
Drop a word onto each iamge: <br>
<ul class = "row">
<li id="drop1" class="dropZones images"><img src="image1.jpg"></li>
<li id="drop2" class="dropZones images"><img src="image2.jpg"></li>
</ul>
<ul class = "row">
<li id="drop_zone3" class="dropZones images"><img src="image3.jpg"></li>
<li id="drop_zone4" class="dropZones images"><img src="image4.jpg"></li>
</ul>
</div>
I am trying to create this using document.createElement() etc. But am having difficulty doing this efficiently.
The purpose of the rows (in above code) are for formatting (using bootstrap4), since there are 6 pictures total in my array, and I want 2 rows of 3.
Below, I have an array that holds all the images' src's. This array is passed into the function. I'm able to create one row/ul, with all of the li's/images inside. But I want to be able to create what I have above, with as little hard coding as possible and as efficiently as possible.
I have:
function createType3(arr)
{
var count = 0;
var length = arr.length;
var list = document.createElement("ul");
list.classList.add("row");
for (var i = 0; i < length; i++)
{
//create list and associated ids and classes
var listPiece=document.createElement("li");
listPiece.classList.add("dropZones","images","list-inline");
listPiece.setAttribute("id","dropZone");
//create image tags and append
var imageSRC = document.createElement("IMG");
imageSRC.setAttribute("src",arr[i]);
listPiece.appendChild(imageSRC);
list.appendChild(listPiece);
}
return list;
}
I'm having trouble doing this, thank you.
You could create a document fragment and add list elements to it. Create a new list whenever i % 3 is zero. Make that 3 an argument so that you can use the function also for lists of any other number of entries:
function createType(arr, groupSize = 3) {
var lists = document.createDocumentFragment(),
list;
for (var i = 0; i < arr.length; i++) {
if (i % groupSize === 0) {
list = document.createElement("ul");
list.classList.add("row");
lists.appendChild(list);
}
//create list and associated ids and classes
var listPiece = document.createElement("li");
listPiece.classList.add("dropZones","images","list-inline");
listPiece.setAttribute("id","dropZone");
//create image tags and append
var imageSRC = document.createElement("IMG");
imageSRC.setAttribute("src", arr[i]);
listPiece.appendChild(imageSRC);
list.appendChild(listPiece);
}
return lists;
}
You could call it like this:
var frag = createType(["img1.png","img2.png","img3.png","img4.png"], 3);
document.body.appendChild(frag); // add it somewhere in your HTML page
Related
I have multiple ul elements on my page and I need to add a class name to some and those with that class name need to randomize. I can do it by id but I can only have one id on a page so I can't do that. I need a JavaScript solution without JQuery. Any help is appreciated. Thank you.
Here is what I used to randomize it by id (it only does one ul though):
var thisUL = document.getElementById("myID");
for (var i = thisUL .children.length; i >= 0; i--) {
thisUL.appendChild(thisUL.children[Math.random() * i | 0]);
}
<ul id="myID">
<li>random1a</li>
<li>random1b</li>
<li>random1c</li>
</ul>
<ul id="myID">
<li>random2a</li>
<li>random3b</li>
<li>random4c</li>
</ul>
<ul id="myID">
<li>random3a</li>
<li>random3b</li>
<li>random3c</li>
</ul>
Each li would need to stay within its own ul.
First of all, you should use class attribute, then use getElementsByClassName() to target all the elements having the class. Then iterate them with for loop and you have the rest of the functionality:
var ulList = document.getElementsByClassName("myElement");
for (let j = 0; j < ulList.length; j++) {
var thisUL = ulList[j];
for (let i = thisUL.children.length; i >= 0; i--) {
thisUL.appendChild(thisUL.children[Math.random() * i | 0]);
}
}
<ul class="myElement">
<li>random1a</li>
<li>random1b</li>
<li>random1c</li>
</ul>
<ul class="myElement">
<li>random2a</li>
<li>random3b</li>
<li>random4c</li>
</ul>
<ul class="myElement">
<li>random3a</li>
<li>random3b</li>
<li>random3c</li>
</ul>
I want to know that there are how many ways in JS to create sub tags and their classes names from a given array eg array =['one','two','three','four','five'].
If I be more specific I have already created main tags ie <li class="card"></li>............<li class="card"></li> of class deck through JS
`let displayCards = document.querySelector('.deck');
for (i=0; i < symbols.length; i++) {
let cards = document.createElement('li');
cards.classList.add('card');
displayCards.appendChild(cards);
}`
this is the end result I want:
<ul class="deck">
<li class="card">
<i class="one"></i>
</li>
<li class="card">
<i class="two"></i>
</li>
<li class="card">
<i class="three"></i>
</li>
</ul>
SO...How many ways to create sub-tags and sub-classes of all class card of above mentioned array.
Many Thanks
Here's what you can do it's just like what you tried already.
Html:
<ul class="deck">
</ul>
JS:
<script>
$(document).ready(function () {
var symbols = ['one', 'two', 'three', 'four', 'five']
let displayCards = document.querySelector('.deck');
for (i = 0; i < symbols.length; i++) {
let cards = document.createElement('li');
cards.classList.add('card');
let childCard = document.createElement('i');
childCard.classList.add(symbols[i]);
childCard.innerHTML += symbols[i];
cards.appendChild(childCard);
displayCards.appendChild(cards);
}
});
</script>
im having a bit of trouble with the code below:
Html:
<p>click to <a onclick ="sortList(); return false;" href="#">sort</a></p>
<ul id="fruits">
<li>apple</li>
<li>orange</li>
<li>banana</li>
</ul>
Javascript:
function sortList(listId) {
var list = document.getElementbyId(listId);
var children = list.childNodes;
var listItemsHTML = new Array();
for (var i = 0; i < children.length; i++) {
if (children[i].nodeName === "LI") {
listItemsHTML.push(children[i].innerHTML);
}
}
listItemsHTML.sort();
list.innerHTML="";
for (var i = 0; i < listItemsHTML.length; i++) {
list.innerHTML += "<li>" + listItemsHTML[i] + "</li>";
}
}
however, when i try and click the link to sort the html does nothing and im not sure what the problem is. i am referencing and was able to use changeit and echo function to produce an alert message in the .js file just cant sort
You need to pass the listId to the function as an argument like onclick ="sortList('fruits'); return false;" and change document.getElementbyId() to document.getElementById() which is a typo
function sortList(listId) {
var list = document.getElementById(listId);
var children = list.childNodes;
var listItemsHTML = new Array();
for (var i = 0; i < children.length; i++) {
if (children[i].nodeName === "LI") {
listItemsHTML.push(children[i].innerHTML);
}
}
console.log(listItemsHTML);
listItemsHTML.sort();
list.innerHTML="";
for (var i = 0; i < listItemsHTML.length; i++) {
list.innerHTML += "<li>" + listItemsHTML[i] + "</li>";
}
}
<p>click to <a onclick ="sortList('fruits'); return false;" href="#">sort</a></p>
<ul id="fruits">
<li>apple</li>
<li>orange</li>
<li>banana</li>
</ul>
Firstly, it's document.getElementById ... capital B in ById
Secondly, use list.children rather than list.childNodes - don't need to care about text nodes
Thirdly, use list.appendChild on a sorted list to move the existing nodes, rather than mucking around with innerHTML
function sortList(listId) {
var list = document.getElementById(listId);
Array.from(list.children).sort((a, b) => a.textContent > b.textContent).forEach(li => list.appendChild(li));
}
Or, if you're not comfortable with ES2015+
function sortList(listId) {
var list = document.getElementById(listId);
Array.from(list.children).sort(function (a, b) {
return a.textContent > b.textContent;
}).forEach(function (li) {
return list.appendChild(li);
});
}
and finally, change
<a onclick ="sortList(); return false;" href="#">
to
<a onclick ="sortList('fruits'); return false;" href="#">
I know its already answered, but of thought of providing little different version.
Use buttons instead of <a>, Using 'href='#' is not a good practice.
Never create a element from string. Always use document.createElement. Its better!
Write a separate listener for triggering functions. Don't write in HTML itself. It will be harder to manage once application grows.
HTML
<p>click to <button class="sort">sort</button></p>
<ul id="fruits">
<li>apple</li>
<li>orange</li>
<li>banana</li>
</ul>
JavaScript
<script type="text/javascript">
function sortList() {
var fruitCollection = [],
fruitsDOM = document.querySelector('#fruits'),
fruitsLists = document.querySelectorAll('li');
fruitsLists.forEach(function(item) {
fruitCollection.push(item.textContent);
});
fruitCollection.sort();
fruitsDOM.innerHTML = null;
fruitCollection.forEach(function(item) {
var newNode = document.createElement('li');
newNode.textContent = item;
fruitsDOM.appendChild(newNode);
});
}
document.querySelector('.sort').addEventListener('click', sortList);
</script>
I'm trying to append child to listing but what I want to do is to append it in the place ordering by data-price.
my template:
<ul>
<li data-price="18"></li>
<li data-price="27"></li>
<li data-price="28"></li>
<li data-price="31"></li>
<li data-price="99"></li>
<li data-price="101"></li>
<li data-price="191"></li>
</ul>
my js what I've tried so far:
var template = '<li data-price="100"></li>';
$('ul').find('li').filter(function() {
return $(this).attr("data-price") > 99;
}).after(template);
so if the price is 100 it should be appended by price ordering and in this case where price is greater then 99 but less then 101, but i dont have any working solution for that.
I'm not sure if this is the best way to do it and if it'll always work, but it works for your question. Try it out
var template = '<li data-price="100">100</li>';
var checkPrice = $(template).attr("data-price");
var appendBefore = $('ul li').filter(function(){
return parseInt($(this).attr("data-price")) > checkPrice-1;
})[0];
console.log(appendBefore);
$(appendBefore).before(template);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-price="18">18</li>
<li data-price="27">27</li>
<li data-price="28">28</li>
<li data-price="31">31</li>
<li data-price="99">99</li>
<li data-price="101">101</li>
<li data-price="191">191</li>
</ul>
check if that is what you need:
https://jsfiddle.net/3er0da9c/
var template = '<li data-price="100"></li>';
var itemValue = parseInt($(template).attr('data-price')); //Getting value that we should compare
var value, smaller = 0, smallerItem; //We will need those variables to know where to place our "template"
smallerItem = $('ul > li:first-of-type'); //Set the smaller item in our list to be the first one. Change that if your list wont be always asc sorted
$('ul > li').each(function(){ //run through the given list
value = parseInt($(this).attr('data-price'));
if ((itemValue == value) || ( itemValue > value )){ //if the actual item is equal, put our item right after it. If the item is smaller then our number, we save it and keep running
smaller = value;
smallerItem = $(this);
}
});
if (smaller != 0) //This will happens when we have at least one item smaller then our number
smallerItem.after(template);
else
smallerItem.before(template); //else, we add our number at top
Ok I have an HTML list containing the data I need.
It looks like this
ul
li[data-trainer]>trainee
li[data-trainer]>trainee
li[data-trainer]>trainee
I iterate it and want to make an object that looks like this
{
"Trainer":{0:Trainee1},
"Trainer2":{1:Trainee2,2:Trainee3,3:Trainee4}
}
I tried this and a bunch more
var Data = new Object();
var i = 0;
$(".blah-blah-ul li.active").each(function(){
i++;
var trainer = $(this).attr("data-trainer");
var trainee = $(this).text();
Data[trainer] = {};
Data[trainer][i] = trainee;
})
console.log(Data);
Data[trainer][i] = trainee leaves me with only the last trainee in the list.
Data from console.log:
Object
Trainer1: Object
2: Trainee2
Trainer3: Object
4: Trainee6
I tried making an array and using push or making a string but that didn't work.
If someone could please recommend a proper solution, it would be greatly appreciated.
Here's the HTML
<ul class="blah-blah-ul">
<li class="active" data-trainer="Trainer1">Trainee1</li>
<li class="active" data-trainer="Trainer1">Trainee2</li>
<li data-trainer="Trainer2">Trainee3</li>
<li data-trainer="Trainer2">Trainee4</li>
<li class="active" data-trainer="Trainer3">Trainee5</li>
<li class="active" data-trainer="Trainer3">Trainee6</li>
</ul>
Your problem was in order to have more than one value assigned to the element in the array, the sub element must be an array. This allows for adding multiple Trainee to the Trainer item in the Data object.
var Data = new Object();
var i = 0;
$(".blah-blah-ul li.active").each(function(){
i++;
var trainer = $(this).attr("data-trainer");
var trainee = $(this).text();
if(typeof Data[trainer] === 'undefined') {
Data[trainer] = {};
}
Data[trainer][i] = {trainee};
})
console.log(Data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="blah-blah-ul">
<li class="active" data-trainer="Trainer1">Trainee1</li>
<li class="active" data-trainer="Trainer1">Trainee2</li>
<li data-trainer="Trainer2">Trainee3</li>
<li data-trainer="Trainer2">Trainee4</li>
<li class="active" data-trainer="Trainer3">Trainee5</li>
<li class="active" data-trainer="Trainer3">Trainee6</li>
</ul>
Documentation on Javascript Arrays using Push, can be found here w3schools
var Data = {};
var i = 0;
$(".blah-blah-ul li.active").each(function(){
i++;
var trainer = $(this).attr("data-trainer");
var trainee = $(this).text();
Data[trainer] = {};
Data[trainer][i] = trainee;
})
console.log(Data);
Try the following approach:
Data[trainer][i] = trainee;
and you can find more info here:
How can I add a key/value pair to a JavaScript object?