Set div id's from array content - javascript

I'm trying to figure out how to give 16 different divs the id names that are stored in a 16 elements long array.
This is so that I can randomize the divs "placement" for a memory game, since there will be 8 different div styles that will change along with the div id if that is possible.
My plan is to have the same name for the div id as for the style for that specific div.
Is there any way to set the first div's id and style as the value in myarray[0], and the second div's id and style as myarray[1], and so on?
EDIT:
var card = ["orange","orange","pink","pink","red","red","purple","purple",
"blue","blue","green","green","brown","brown","yellow","yellow"];
for(var j, x, i = card.length; i; j = parseInt(Math.random() * i),
x = card[--i], card[i] = card[j], card[j] = x);
then later in the body I'm trying to achieve something that represents this:
<div id="card[0]"></div>
<div id="card[1]"></div>
<div id="card[2]"></div>
and so on...

Here is a solution for randomising class names using pure JavaScript.
Updated answer
I have updated my solution now that the question was clarified, here is it adapted to your colors. I have set the background-color of the .cards to the colors set in the array. This could easily be done using the id as well, I recommend against using [] characters in an id though as I think I'm not sure if that's standards compliant.
jsFiddle
var colors = [
"orange","orange","pink","pink","red","red","purple","purple",
"blue","blue","green","green","brown","brown","yellow","yellow"
];
var divs = document.getElementsByClassName("card");
while (divs.length > 0) {
var i = Math.floor(Math.random() * colors.length);
divs[0].style.backgroundColor = colors[i];
colors.splice(i, 1);
divs = [].slice.call(divs, 1);
}
Original answer
Given an array of ids and a set of HTML elements, a random id will be assigned to each element from ids.
jsFiddle
JavaScript
var ids = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
var divs = document.getElementsByClassName("game-element");
while (divs.length > 0) {
var i = Math.floor(Math.random() * ids.length);
divs[0].id = 'item-' + ids[i];
ids.splice(i, 1);
divs = [].slice.call(divs, 1);
}
HTML
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
<div class="game-element"></div>
CSS
.game-element {
width:10px;
height:10px;
float:left;
}
#item-1 { background-color:#F00; }
#item-2 { background-color:#0F0; }
#item-3 { background-color:#00F; }
#item-4 { background-color:#FF0; }
#item-5 { background-color:#F0F; }
#item-6 { background-color:#0FF; }
#item-7 { background-color:#A0A; }
#item-8 { background-color:#0AA; }
#item-9 { background-color:#AA0; }
#item-10 { background-color:#000; }

Assign each div a randomdiv class or something like that. That will ensure you can select on the ones you want without affecting other divs.
Then you can do this
var idArr = [/**random ids here**/];
$( ".randomdiv" ).each(function( index ) {
$(this).attr("id",idArr[index]);
});
That will loop over every div with the class randomdiv and assign it a value from idArr which you can define however you want, I guess with some type of randomization function for your use case
Update
With your updates to the question I'm seeing an issue. You have non unique ids that you want to set. ids must be unique. If you want to assign multiple of them to be the same you want to use classes. So the code would instead look like this
var card = ["orange","orange","pink","pink","red","red","purple","purple",
"blue","blue","green","green","brown","brown","yellow","yellow"];
$( ".randomdiv" ).each(function( index ) {
$(this).addClass(card[index]);
});
And then you could define the style you want with css like this
.randomdiv.blue{
background-color:blue;
}
.randomdiv.green{
background-color:green;
}
...

Hard to know exactly what you're after but if using jQuery you could do something like this:
HTML:
<div class="random"></div>
<div class="random"></div>
<div class="random"></div>
JavaScript:
var myarray = ["one","two","three"];
// loop through all divs
$('div.random').each(function(index) {
// set div id to array value
$('div').attr('id', myarray[index]);
});
Result:
<div class="random" id="one"></div>
<div class="random" id="two"></div>
<div class="random" id="three"></div>
Additional Comments:
Would be worth ensuring or at least checking that the array length is equal to the number of div elements, otherwise you may receive exceptions.

Your page could be either rendered in server side or client side
1) in server side, that is much more easier with your server side language (e.g. C#) and framework (e.g. ASP.NET)
2) in client side, you could generate your DOM based on any JavaScript template (e.g. underscore template) and render it by passing the array as data model)
you may refer to underscore template method: http://underscorejs.org/#template
EDIT
for an example on server side (I use C# and MVC razor view as example, but it could be the same idea if you use any other language and web server).
#{ ids = ... }
#foreach (var id in ids)
{
<div id="#id"></div>
}
the code will help you to generate the div with ids you defined.
and on client side (I use underscore template, but again same idea if you use any other engine)
var list = "_.each(ids, function(id) {<div id='<%id%>'></div>});";
_.template(list, {ids: ['id1', 'id2', 'id3']});
this will generate 3 div with the ids listed.
Update
It's better to generate the id when generating the div rather than firstly generate the div then modify its id.

Related

Shuffle only one child DIV based on class

I would like to shuffle specific DIVs (based on class) around on each page load.
Note i'm using a Wordpress Theme and as such, do not have full control over HTML structure without changing base themes (which i'm not willing to do)
jfiddle is here.
$(function() {
$(".shuffle").each(function() {
var parent = $(this),
divs = parent.children().remove();
while (divs.length) {
parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
}
});
});
Parent DIV class = "shuffle"
Child DIVs class = "shuffle-child"
What am I doing wrong? Apologies for lack of JS experience!!
For your particular scenario you can use the following, adapted for jQuery from https://stackoverflow.com/a/11972692/2413733 #AlexeyLebedev's answer using the Fischer-Yates Shuffle.
var shuffleKids = $('.shuffle-kids'), // the elements to shuffle
shuffle = shuffleKids.parent(); // the container div
for (var i = shuffleKids.length; i >= 0; i--) {
shuffle.append(shuffle.children()[Math.random() * i | 0]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='shuffle'>
<div class='shuffle-kids'>milk</div>
<div class='shuffle-kids'>butter</div>
<div class='shuffle-kids'>eggs</div>
<div class='shuffle-kids'>orange juice</div>
<div class='shuffle-kids'>bananas</div>
</div>

JavaScript tag system: show only the divs that have all the classes listed in an array, else hide

Please explain how to do this!
I want to be able to hide/show a div based on its classes and an array.
If something is in an array, then it will only show divs which have the something class.
If nothing is in an array, every div will be shown.
If something and johnskeet are in the array, then it will only show divs which have both the something and johnskeet classes.
At a high level, one option would to have all of the divs hidden by default and then use document.querySelectorAll() to apply an 'unhidden' style to each div that is in the array.
Here is a question that should help with selecting divs with multiple classes that should help as well.
queryselectorAll - find an element with more than one matching class
I would recommend you to dynamically generate appropriate selector from the array, show all the matching elements and hide all other elements by default:
JavaScript
const classes = ['foo', 'bar', 'baz']
,selector = classes.map(x => '.' + x).join('')
$(selector).show()
CSS
div {
display: none;
}
See demo on JS Fiddle.
Alternatively, if you work on a high amount of elements, it would be better to generate appropriate style sheet in JavaScript:
const classes = ['foo', 'bar', 'baz']
,selector = classes.map(x => '.' + x).join('')
,$style = $(`<style>div {display: none;} div${selector} {display: block;}</style>`)
$('head').append($style)
To revert that, simply remove the <style> element by calling $style.remove().
See demo on JS Fiddle.
Assuming the elements are initially shown, you only need to hide the undesired ones. You can insert a stylesheet with
var rule = array.map(c => 'div:not(.' + CSS.escape(c) + ')').join()
+ '{display:none}';
sheet.insertRule(rule, 0);
var array = ["something", "johnskeet"];
var rule = array.map(c => 'div:not(.' + CSS.escape(c) + ')').join() + '{display:none}';
var style = document.createElement('style');
document.head.appendChild(style);
var sheet = style.sheet;
sheet.insertRule(rule, 0);
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
However, if some elements may already be hidden, you will need to set the desired display with higher specificity. The problem is that some elements are by default block-level, and some are inline-level. jQuery's toggle can be helpful to detect that:
$('div').each(function() {
$(this).toggle(array.every(c => this.classList.contains(c)));
});
var array = ["something", "johnskeet"];
$('div').each(function() {
$(this).toggle(array.every(c => this.classList.contains(c)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
Another option would be display: revert, but it's not widely supported yet.
You may do as follows with pure JS. Run the code multiple times to see the results for randomly generated classArray.
var classes = ["something","johnskeet"],
classArray = classes.reduce((p,c) => Math.random() > 0.5 ? p.concat(c) : p,[]),
divs = document.querySelectorAll(".something, .johnskeet");
arrayStatus.textContent = "The current classes array is: " + JSON.stringify(classArray);
for (var div of divs) div.style.display = classArray.length === div.classList.length ? classArray.every(c => [...div.classList].includes(c)) ? "" : "none"
: !classArray.length ? "" : "none";
.something {background-color: paleGreen}
.johnskeet {background-color: tomato}
.something.johnskeet {background-color: thistle}
<p id="arrayStatus"></p>
<div class="something johnskeet">SJ</div>
<div class="johnskeet">J</div>
<div class="johnskeet">J</div>
<div class="something">S</div>
<div class="something">S</div>
<div class="johnskeet">J</div>
<div class="something johnskeet">SJ</div>
<div class="johnskeet">J</div>
<div class="something johnskeet">SJ</div>
No need to do anything fancy.
var array = ["something", "foo"];
Need to convert your array in such way that creates needed selector.
$('div').not("."+array.join(".")).hide();
Show element which has at-least once class from array.
$('div').not("."+array.join(",.")).hide();
If you've large amount of elements, you can use each() also.
var array = ["something", "johnskeet"];
var selector="";
$.each(array, function(key, value){
selector += "."+value;
});
console.log(selector);
$('div').not(selector).hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
<div class="dummy">dummy</div>

div#d1 toggle on p#1 click - howTo?

I am trying to toggle a div when its name is clicked.
I have multiple coupls like that in my page, and I want it to work as
"when <p id= "d2"> is clicked => <div id="d2"> is toggled".
I tried those functions:
$(document).ready(function(){
$("p").click(function(){
$("div#" + $(this).attr('id')).toggle();
});
});
function rgt() {
//document.body.innerHTML = "";
var id = "d" + this.id;
var situation = document.getElementById(id).style.display;
if (situation == "none") {
situation = "block";
}
else {
situation = "none";
}
}
function showHide(theId) {
if (document.getElementById("d" + theId).style.display == "none") {
document.getElementById("d" + theId).style.display = "block";
}
else {
document.getElementById("d" + theId).style.display = "none";
}
}
I can't make it Work!!! Why is it?
the browser says:"no 'display' property for null"...
I will be more than happy to solve it with simple jquery
Ensure Your id Attributes Are Unique
Assuming that your id attributes are unique, which they are required to be per the specification:
The id attribute specifies its element's unique identifier (ID). The
value must be unique amongst all the IDs in the element's home subtree
and must contain at least one character. The value must not contain
any space characters.
You should consider renaming your id attributes to d{n} and your paragraphs to p{n} respectively as seen below :
<button id='p1'>p1</button> <button id='p2'>p2</button> <button id='p3'>p3</button>
<div id='d1'><pre>d1</pre></div>
<div id='d2'><pre>d2</pre></div>
<div id='d3'><pre>d3</pre></div>
which would allow you to use the following function to handle your toggle operations :
$(function(){
// When an ID that starts with P is clicked
$('[id^="p"]').click(function(){
// Get the proper number for it
var id = parseInt($(this).attr('id').replace(/\D/g,''));
// Now that you have the ID, use it to toggle the appropriate <div>
$('#d' + id).toggle();
})
});
Example Using Unique IDs
You can see an interactive example of this approach here and demonstrated below :
Consider Using data-* Attributes
HTML supports the use of data attributes that can be useful for targeting specific elements through jQuery and associating them to other actions. For instance, if you create an attribute on each of your "p" elements as follows :
<button data-toggles='d1'>p1</button>
<button data-toggles='d2'>p2</button>
<button data-toggles='d3'>p3</button>
and then simply change your jQuery to use those as selectors :
$(function(){
// When an element with a "toggles" attribute is clicked
$('[data-toggles]').click(function(){
// Then toggle its target
$('#' + $(this).data('toggles')).toggle();
});
});
Is this you are looking?
$("#p1").on("click", function() {
$("#d1").toggle();
});
js fiddle: https://jsfiddle.net/Jomet/09yehw9y/
jQuery(function($){
var $toggles = $('.divToggle');
var $togglables = $('.togglableDiv');
$toggles.on('click', function(){
//get the div at the same index as the p, and toggle it
$togglables.eq($toggles.index(this)).toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="divToggle">Show Me 1</p>
<p class="divToggle">Show Me 2</p>
<p class="divToggle">Show Me 3</p>
<div class="togglableDiv">Weeee 1</div>
<div class="togglableDiv">Weeee 2</div>
<div class="togglableDiv">Weeee 3</div>
Minimal approach using classes. This solution assumes the order of the p elements in the dom are in the same order as the divs are in the order. They do not have to be contiguous, but the order does matter with this solution.
ids are not the droids you are looking for.
An id needs to be unique. If you want to classify something one would suggest to use classes. You can actually use serveral of them for some fancy stuff. How about something like this:
<p class="toggle one">one</p>
<div class="toggle one" style="display:none">content one</div>
Straight forward. Every element that is a switch or switchable gets the class toggle. Each pair of switch and switchable(s) gets an additional identifier (like one, two, ...).
Simple JScript Implementation:
Now how about not using JQuery to work with that? Sure it i$ handy, but it hides all that neat stuff one would eventually like to learn her/himself!
var myToggle = {};
(function(module) {
"use strict";
(function init() {
var elements = document.getElementsByClassName("toggle");
var element;
var i = elements.length;
while (i) {
i -= 1;
element = elements[i].className;
elements[i].setAttribute("onclick", "myToggle.swap(\"" + element + "\")");
}
}());
module.swap = function(element) {
var couple = document.getElementsByClassName(element);
var i = couple.length;
while (i) {
i -= 1;
if (couple[i].style.display === "none" && couple[i].tagName === "DIV") {
couple[i].style.display = "block";
} else if (couple[i].tagName === "DIV") {
couple[i].style.display = "none";
}
}
};
}(myToggle));
<p class="toggle one">one</p>
<div class="toggle one" style="display:none">content one</div>
<p class="toggle two">two</p>
<div class="toggle two" style="display:none">content two 1</div>
<div class="toggle two" style="display:none">content two 2</div>
var myToggle = {} is the object we use to keep our little program contained. It prevents that our code conflicts with other declarations. Because what if some plugin on our site already declared a function called swap()? One would overwrite the other!
Using an object like this ensures that our version is now known as myToggle.swap()!
It may be hard to follow how it got to that name. Important hint: something looking like this... (function() { CODE } ()) ...is called an immediately-invoked function expression. iffy! It's a function that is immediatly executed and keeps its variables to itself. Or can give them to whatever you feed it in the last ()-pair.
Everything else is as verbose as can be... no fancy regular expressions, hacks or libraries. Get into it!

Get all items that start with class name

I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:
<form>
<input type="text" onfocus="showfields(1);">
<input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
function showfields(page){
//hide all items that have a class starting with page*
var patt1 = /^page/;
var items = document.getElementsByClassName(patt1);
console.log(items);
for(var i = 0; i < items.length; i++){
items[i].style.display = "none";
}
//now show all items that have class 'page'+page
var item = document.getElementsByClassName('page' + page);
item.style.display = '';
}
</script>
When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page').
The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.
getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).
The best approach is to use multiple classes…
<div class="page page1">
i.e. This div is a page, it is also a page1.
Then you can simply document.getElementsByClassName('page').
Failing that, you can look to querySelector and a substring matching attribute selector:
document.querySelectorAll("[class^=page]")
… but that will only work if pageSomething is the first listed class name in the class attribute.
document.querySelectorAll("[class*=page]")
… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".
That said, you could use the last approach and then loop over .classList to confirm if the element should match.
var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
for (var i = 0; i < potentials.length; i++) {
var potential = potentials[i];
console.log(potential);
classLoop:
for (var j = 0; j < potential.classList.length; j++) {
if (potential.classList[j].match(/^page/)) {
console.log("yes");
potential.style.background = "green";
continue elementLoop;
}
}
console.log("no");
potential.style.background = "red";
}
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Previous answers contain parts of the correct one, but none really gives it.
To do this, you need to combine two selectors in a single query, using the comma , separator.
The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).
By combining both selectors, we have our classStartsWith selector:
document.querySelectorAll('[class^="page"],[class*=" page"]')
.forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
You can use jQuery solution..
var $divs = $('div[class^="page"]');
This will get all the divs which start with classname page
$(document).ready(function () {
$("[class^=page]").show();
$("[class^=page]").hide();
});
Use this to show hide div's with specific css class it will show/hide all div's with css class mention.

Calculate the number of html element with js

I have multiple div elements with same id='mydiv'.I want to calculate these divs and Iam using the code
document.getElementById('mydiv').length
But it is not working
What you should do is use class instead of ID's. ID is for one element only, class is for multiple.
http://jsfiddle.net/d7AHV/
It won't work as getElementById will always return an element with the specified ID and null if the specified ID doesn't exist
From ECMA
getElementById(elementId) This method returns a Element. The elementId
parameter is of type DOMString.
What you can do is to assign each div with class
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>​​​​​​​​​
And iterate over:
var divs = document.getElementsByTagName('div');
var count = 0;
for(var i = 0; i < divs.length; i++) {
if(divs[i].className == 'mydiv') count++;
}
alert(count);
If your clients support document.getElementsByClassName(), it's even more concise:
alert(document.getElementsByClassName('mydiv').length)
You've been told about multiple elements with the same ID, but in rare cases it might be unavoidable (e.g. an XML document over which you have no control). The only adverse behaviour is that selecting by ID will usually only return the first one (but that's not guaranteed).
You can count elements with the same id by looping over all the elements in the document and counting the ones with a matching id, e.g.
function countSameIds(id) {
var allNodes = document.getElementsByTagName('*');
for (var i=allNodes.length, count=0; i; ) {
if (allNodes[--i].id == id) {
++count;
}
}
return count;
}

Categories