I'm new to JS and jQuery but I've been trying to use the addClass() and removeClass with some Javascript variables and don't know what I'm doing wrong.
I have this 1–5 star rating system.
I want it to change classes when hovering and save rating when I click.
The HTML looks like this:
<span class="icon-rating-empty" id="blob1"></span>
and so on for blobs 2–5.
The JS I currently have is
var blob1 = document.getElementById('blob1');
var blob2 = document.getElementById('blob2');
var blob3 = document.getElementById('blob3');
var blob4 = document.getElementById('blob4');
var blob5 = document.getElementById('blob5');
var rating = 0;
blob1.addEventListener('hover', function() {
$(blob1).addClass("icon-rating-full").addClass("green-blob").removeClass("icon-rating-empty")
},
function() {
$(blob1).addClass("icon-rating-empty").removeClass("green-blob").removeClass("icon-rating-full")
});
blob1.addEventListener('click', function() {
rating = 1;
});
This doesn't work—I'm sure I don't know how to handle variables with the jQuery, but can't find any article on what I'm supposed to do.
I've tested it and if I use $("#blob1") instead of $(blob1) it works, but I'd like to use the variables because I have more in plan.
You're not far off. You will need to set up two sets of event listeners: one for when the user clicks on a star, and one for when the user hovers over a star.
I suggest saving the "rating" as a variable. When the user clicks a star, you adjust the rating. I used a data attribute to keep track of the value of each star. After adjusting the rating, you loop through the elements and add or remove classes accordingly.
Hovering adds a layer of complexity. Every time there is mouseover, you will need to loop over the star elements and update the classes as though that was the new rating. When you mouseout, you will update the classes again according to the rating that you saved.
var rating = 0;
var stars = $('li');
// Set up listeners
$('li').on('click', function(){
rating = parseInt($(this).data('val'));
drawStars(rating);
});
$('li').hover(
function(){
tempRating = parseInt($(this).data('val'));
drawStars(tempRating);
},
function(){
drawStars(rating);
}
);
// This function loops through the "star" elements and adds and removes a 'selected' class
function drawStars(numStars){
// Reset the colour by removing the selected class from all elements
for(var i = 0; i < stars.length; i++){
$(stars[i]).removeClass('selected');
}
// Add a selected class to some of the elements
for(var i = 0; i < numStars; i++){
$(stars[i]).addClass('selected');
}
}
See this jsfiddle: https://jsfiddle.net/ffz5y9fm/5/
Untested:
<span class="rating">
<span data-star="0">STAR</span>
<span data-star="1">STAR</span>
<span data-star="2">STAR</span>
<span data-star="3">STAR</span>
<span data-star="4">STAR</span>
<span data-star="5">STAR</span>
</span>
<script>
try{
var elements = document.querySelectorAll('.rating'),
listener = function(e){
var a = this, parent = a.parentNode, value = parseInt( a.getAttribute('data-star') );
// reset
parent.classList = 'rating';
// add class
parent.classList.add( 'star-'+value );
};
// get all elements and attach listener
for( var i = 0; i < elements.length; ++i ){
var current = elements[i], childs = current.children;
for( var ii = 0; ii < childs.length; ++ii ){
childs[ii].addEventlistener('mouseenter',listener,false);
}
}
} catch(e){ console.log('error',e); }
</script>
If something doesn't work just report here.
Related
This is supposed to be a very simple dropdown FAQ system, I know how to do this in jQuery but I want to learn plain JS.
I just want the individual clicked triggers to toggle the is-visible class to the content divs next to the clicked trigger. Like $(this).next addClass — just in JS.
I've really tried to search for this issue but 90% that shows up is how to do it in jQuery :-p
https://jsfiddle.net/48ea3ruz/
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
// access to individual triggers:
var trigger = allTriggers[i];
}
var allContent = document.querySelectorAll('.faq-content');
for (var i = 0; i < allContent.length; i++) {
// access to individual content divs:
var content = allContent[i];
}
// I don't know how to target the faq-content div next to the clicked faq-trigger
this.addEventListener('click', function() {
content.classList.toggle('is-visible');
});
Would really appreciate some advice! :-)
Use nextSibling, when you are iterating .faq-trigger
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextSibling.classList.toggle('is-visible');
});
}
nextSibling will also consider text-nodes, try nextElementSibling also
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextElementSibling.classList.toggle('is-visible');
});
}
I am trying to dynamically create a set of check-boxes that each call a function differently when clicked
function initAllButtons(variable, length)
{
for(c = 0; c < length; c++)
{
clicks.push(true);
}
for(i = 0; i < length; ++i)
{
var label = document.createElement("label");
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = true;
checkbox.value = btns[i];
checkbox.class = "colorCoder";
label.appendChild(checkbox);
document.getElementById('Buttons').appendChild(checkbox);
$('#Buttons').on('click', function(){updateData(i,clicks);});
}
}
Btns is just an array of strings. I really want to call the UpdateData function (which I have tested and works like it should) with the value or index of the button pressed, but nothing seems to be working.
This version just calls updateData ten times with index = 10. It obviously is not looking at the buttons as individual things. What am I doing wrong?
When dynamically adding elements to the dom, attaching event listeners gets tricky. This is a perfect use case for delegate on a parent container:
var clickcontainer = document.getElementById('clickcontainer');
clickcontainer.addEventListener('click', function(e) {
var target = e.target || e.srcElement;
e.stopPropagation();
}, false);
Use closures to get this behavior, the closure function will create a new isolated scope and store the state of the variables.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function clickClosure(i, clicks){
return function(){
updateData(i,clicks);
}
}
function initAllButtons(variable, length)
{
for(c = 0; c < length; c++)
{
clicks.push(true);
}
for(i = 0; i < length; ++i)
{
var label = document.createElement("label");
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = true;
checkbox.value = btns[i];
checkbox.class = "colorCoder";
label.appendChild(checkbox);
document.getElementById('Buttons').appendChild(checkbox);
var clickFnct = clickClosure(i, clicks);
$('#Buttons').on('click', clickFnct);
}
}
The problem is that you are doing nothing in your click handler to reference the clicked element. To do that you need to specify selector as parameter to on(). That might look like this:
$('#Buttons').on('click', ':checkbox', function() {
// determine index of clicked item
var index = $('#Buttons :checkbox').index(this);
// call your function
updateData(index,clicks);
}
You should also place this code after your loop as you only need to execute this line of code once.
Guessing by the code you are actually attaching a click event on a button rather than on the checkbox itself. Once you've created the element with document.createElement you can create your jQuery object and use the event handlers jQuery got.
var checkbox = document.createElement("input");
$(checkbox).on('click' function(){
//Code here
}
If you want to keep the value of i you must use a closure. Look at my fiddle:
http://jsfiddle.net/u13Le70g/
I got a problem while writung a code for a Heatmap based on link clicks.
I have a Page with different articel teasers. When i click the link the artical itself opensup. Now i want to track in real time how often which articel is clicked so i can decide which articel is relevant to users and place it like on the first articel space and so on.
Therefor i wrote a function which tracks the clicks with a counter and show them in the div.
Now my problem is. That i cant write like 20 functions for counters and 20 for resets. I want to have one function which can decide which articel was clicked and add +1 to the counter of the link.
My Code for the counter and the reset + the link text gets red after more than 5 clicks.
var count1 = 0;
function heatmap(id) {
if(id==1){
count1++;
document.getElementById("count1").innerHTML = count1;
}
if(count1>=5){
document.getElementById("link1").style.color = "red";
}
}
function reset(id){
if(id==1){
count1=0;
document.getElementById("count1").innerHTML = 0;
}
}
My html code so far
<div style="text-align:center; font-size:20px; font-family: arial;">
<div id="link1" onclick="heatmap(1)">This is the first Link</div><br>
<div id="count1">0</div><br>
<button onclick="reset(1)">RESET</button>
<button onclick="save(1)">SAVE</button>
</div>
Now my main problem is that i only want one function for all the link tracking.
Is there a possibiblity to write the code in a way the variables are dynamicly so that the function can decide which link was clicked.
for example something like:
var count + ID = 0;
function heatmap(ID) {
count + ID ++;
document.getElementById("count" + ID).innerHTML = count+ID;
}
if(count + ID >=5){
document.getElementById("link + ID").style.color = "red";
}
}
function reset(id){
count + ID =0;
document.getElementById("count + ID").innerHTML = 0;
}
}
I already searched this homepage and did some google searches but all i found was working with arrays or lists. But i think this wouldnt realy work for me since i want to give my function an ID and later add this id to the varibale name like count + ID = count | count + ID = count2 same with the document.getElementById("count" + ID).innerHTML = count+ID; = document.getElementById("count1").innerHTML = count1;
As you can see the link got a onclick="heatmap(ID)" this ID will be added to every articel Link and will go from the first articel with 1 to the last articel with like 20.
If i change an Articel the counter will be resetet and the ID will be changed to its position. So there will always be a identifier with the ID which can be used for the counter.
You could loop through all articles and store a counter on each element which you update or reset once the specific button inside the article was clicked:
var articles = document.querySelectorAll('article');
for(var i=0; i < articles.length; i++) {
articles[i].querySelector('.save').addEventListener('click', updateCounter);
articles[i].querySelector('.reset').addEventListener('click', resetCounter);
articles[i]['counter'] = 0;
}
function updateCounter(ev) {
var article = ev.target.parentNode;
article.counter++;
article.querySelector('.counter').innerHTML = article.counter;
/* Some server synchronisation should go here */
}
function resetCounter(ev) {
var article = ev.target.parentNode;
article.counter = 0;
article.querySelector('.counter').innerHTML = article.counter;
/* Some server synchronisation should go here */
}
DEMO
But to permanently store the counters you have to synchronize your results with a server, respectively a database.
If you just want to use one function you could realize it like this:
var articles = document.querySelectorAll('article');
for(var i=0; i < articles.length; i++) {
articles[i].querySelector('.save').addEventListener('click', checkCounter);
articles[i].querySelector('.reset').addEventListener('click', checkCounter);
articles[i]['counter'] = 0;
}
function checkCounter(ev) {
var article = ev.target.parentNode,
button = ev.target;
if(button.classList[0] === 'save') {
article.counter++;
} else if(button.classList[0] === 'reset') {
article.counter = 0;
}
article.querySelector('.counter').innerHTML = article.counter;
}
DEMO
How can I access a dynamically created element using jQuery? Suppose I have the following code:
for (var i = 0; i < count; i++)
{
var div = document.createElement("div");
div.setAttribute("id", "divHour" + i);
var button = document.createElement("button");
button.setAttribute("id", "btnHour" + i);
div.appendChild(button);
document.getElementById("divHours").appendChild(div);
}
How can I access the buttons using jQuery?
To select the button inside your original loop...
for (var i = 0; i < count; i++)
{
var div = document.createElement("div");
div.setAttribute("id", "divHour" + i);
var button = document.createElement("button");
button.setAttribute("id", "btnHour" + i);
div.appendChild(button);
document.getElementById("divHours").appendChild(div);
// moved after the button has been added to the DOM
// do something with the button in jQuery
$("#btnHour" + i).css({width:100})
}
As long as you know the HTML ID of the element. All you need to do is this:
$("#html_id")
jQuery uses CSS selectors.
Give the buttons a class:
div.setAttribute("class", "myButton");
Then you can get all of the buttons with
$('.myButton') ...
For example, to loop over them:
$('.myButton').each(function(){
console.log($(this).attr("id"));
});
If you want to identify each button, parse the number out of the class or give it a data-mynumber attribute and use $(this).data('mynumber')
var $button0 = $('#btnHour0')
var $button1 = $('#btnHour1')
// ... etc ...
Once you have cached the jQuery object, use it as you wish...
$button0.css({width: 400}).animate({width: 200})
EDIT
To access all buttons in a loop...
// assuming `count` is the same as the code used to create the buttons
for (var i = 0; i < count; i++){
var $button = $('#btnHour'+i)
// do stuff with $button here
}
EDIT
Alternatively, to access all button elements that have an ID that starts with btnHour
var $buttons = $('button[id^="btnHour"]')
// do stuff to all buttons here
$buttons.css({width:300})
var buttons=$('button[id^="btnHour"]');
Will give you the whole collection of buttons
Your question is extremely vague, I suspect you want to access a specific button contained within a div that user interacts with. More details are required as to what you want.
EDIT: following is how you can access the index of a button within a click handler.
var buttons=$('button[id^="btnHour"]').click(function(){
var buttonIndex= buttons.index(this);
var div=$('#divHour'+ buttonIndex)
/* can now interact with corresponding div*/
});
Another simpler way to find the parent div is :
$('button[id^="btnHour"]').click(function(){
var $parentDiv=$(this).parent()
})
To target a specific button use eq() method
var thirdButton=$('button[id^="btnHour"]').eq(2);/* indexing is zero based*/
I have a div element in an HTML document.
I would like to extract all elements inside this div with id attributes starting with a known string (e.g. "q17_").
How can I achieve this using JavaScript ?
If needed, for simplicity, I can assume that all elements inside the div are of type input or select.
var matches = [];
var searchEles = document.getElementById("myDiv").children;
for(var i = 0; i < searchEles.length; i++) {
if(searchEles[i].tagName == 'SELECT' || searchEles.tagName == 'INPUT') {
if(searchEles[i].id.indexOf('q1_') == 0) {
matches.push(searchEles[i]);
}
}
}
Once again, I strongly suggest jQuery for such tasks:
$("#myDiv :input").hide(); // :input matches all input elements, including selects
Option 1: Likely fastest (but not supported by some browsers if used on Document or SVGElement) :
var elements = document.getElementById('parentContainer').children;
Option 2: Likely slowest :
var elements = document.getElementById('parentContainer').getElementsByTagName('*');
Option 3: Requires change to code (wrap a form instead of a div around it) :
// Since what you're doing looks like it should be in a form...
var elements = document.forms['parentContainer'].elements;
var matches = [];
for (var i = 0; i < elements.length; i++)
if (elements[i].value.indexOf('q17_') == 0)
matches.push(elements[i]);
With modern browsers, this is easy without jQuery:
document.getElementById('yourParentDiv').querySelectorAll('[id^="q17_"]');
The querySelectorAll takes a selector (as per CSS selectors) and uses it to search children of the 'yourParentDiv' element recursively. The selector uses ^= which means "starts with".
Note that all browsers released since June 2009 support this.
Presuming every new branch in your tree is a div, I have implemented this solution with 2 functions:
function fillArray(vector1,vector2){
for (var i = 0; i < vector1.length; i++){
if (vector1[i].id.indexOf('q17_') == 0)
vector2.push(vector1[i]);
if(vector1[i].tagName == 'DIV')
fillArray (document.getElementById(vector1[i].id).children,vector2);
}
}
function selectAllElementsInsideDiv(divId){
var matches = new Array();
var searchEles = document.getElementById(divId).children;
fillArray(searchEles,matches);
return matches;
}
Now presuming your div's id is 'myDiv', all you have to do is create an array element and set its value to the function's return:
var ElementsInsideMyDiv = new Array();
ElementsInsideMyDiv = selectAllElementsInsideDiv('myDiv')
I have tested it and it worked for me. I hope it helps you.
var $list = $('#divname input[id^="q17_"]'); // get all input controls with id q17_
// once you have $list you can do whatever you want
var ControlCnt = $list.length;
// Now loop through list of controls
$list.each( function() {
var id = $(this).prop("id"); // get id
var cbx = '';
if ($(this).is(':checkbox') || $(this).is(':radio')) {
// Need to see if this control is checked
}
else {
// Nope, not a checked control - so do something else
}
});
i have tested a sample and i would like to share this sample and i am sure it's quite help full.
I have done all thing in body, first creating an structure there on click of button you will call a
function selectallelement(); on mouse click which will pass the id of that div about which you want to know the childrens.
I have given alerts here on different level so u can test where r u now in the coding .
<body>
<h1>javascript to count the number of children of given child</h1>
<div id="count">
<span>a</span>
<span>s</span>
<span>d</span>
<span>ff</span>
<div>fsds</div>
<p>fffff</p>
</div>
<button type="button" onclick="selectallelement('count')">click</button>
<p>total element no.</p>
<p id="sho">here</p>
<script>
function selectallelement(divid)
{
alert(divid);
var ele = document.getElementById(divid).children;
var match = new Array();
var i = fillArray(ele,match);
alert(i);
document.getElementById('sho').innerHTML = i;
}
function fillArray(e1,a1)
{
alert("we are here");
for(var i =0;i<e1.length;i++)
{
if(e1[i].id.indexOf('count') == 0)
a1.push(e1[i]);
}
return i;
}
</script>
</body>
USE THIS I AM SURE U WILL GET YOUR ANSWER ...THANKS