I have multiple button elements and for each of them I want to create a separate input element to load a picture. Button has an img element within that soon will have a source of loaded picture.
Input elements quantity should be the same as number of buttons.
As I looked through some tips here, I firstly created inputs in a loop than tried to trigger click event on each input in a separate loop.
But unfortunately in result I see that all button refer to last input
pix = $("button[id*='picture-add-']") // all buttons I have
for (var i = 0; i < pix.length; ++i){
i_selector = i+1
new_input = $('<input>', {
id:"file-input-" + i_selector.toString(),
type:"file",
name:"name",
style:"display: none;",
accept:"image/gif, image/jpeg, image/png, image/jpeg"}).appendTo('#addNew') // each input is added to main bootstrap window
}
for (let i = 0; i < pix.length; ++i){
i_sel = i+1
pic_element_id = pix[i].id
input_element_id = $('#file-input-' + i_sel.toString())[0].id
$('#' + pic_element_id).click(function(){
$('#' + input_element_id).trigger('click')
console.log(pic_element_id, 'pic_element_id')
console.log(input_element_id)
})
}
Any time I click any button console prints that I pressed the last button. What part of this could be wrong?
Related
I want to attach an event listener to each radio input click, so that I can retrieve that radio input's value and assign it as the value of a new property in the current question object in the allQuestions array.
I'm not sure why I'm having difficulty making choice.addEventListener work.
My HTML:
<div id="quiz"></div>
<button id="button">Next</button>
My JavaScript:
var allQuestions = [{question: "What is the capital of the Czech Republic?",
choices: ["Skopje", "Budapest", "Prague", "Bucharest"],
correctAnswer: 2},
{question: "When was the Declaration of Independence signed?",
choices: ["1492", "1776", "1812", "1791"],
correctAnswer: 1}];
var quiz = document.getElementById("quiz");
var index = -1;
var next = function() {
index += 1;
quiz.innerHTML = "";
for (var i = 0; i < allQuestions[index]['choices'].length; i++) {
var choice = document.createElement('input');
choice.type = 'radio';
choice.name = 'choices';
choice.value = i;
choice.addEventListener('click', function() {
alert('hi');
});
quiz.appendChild(choice);
quiz.innerHTML += allQuestions[index]['choices'][i] + '<br>';
}
};
var button = document.getElementById('button');
button.addEventListener('click', next);
You're trying to use markup and DOM elements at the same time. Here's the main problem:
quiz.appendChild(choice);
quiz.innerHTML += allQuestions[index]['choices'][i] + '<br>';
The first line appends a DOM element with an attached event handler to the quiz element. The second line converts the contents of quiz to an HTML string, appends some further text (markup) to that string, and then parses that HTML and replaces the content of quiz with the parsed result. That wipes out anything not represented in the HTML, including the dynamically-added event handler.
The solution is not to do innerHTML += ..., which is almost always a bad idea. In this particular case, you can do this:
quiz.appendChild(choice);
quiz.appendChild(document.createTextNode(allQuestions[index]['choices'][i]));
quiz.appendChild(document.createElement('br'));
...which also has the advantage that any characters that are special in HTML (like <) are treated literally (because that's what createTextNode does).
Now, having said that, you don't need handlers on every radio button. Instead, you can use event delegation by using a handler on your quiz element, and then using e.target within the handler to know which radio button was clicked:
quiz.addEventListener("click", function(e) {
if (e.target.tagName.toUpperCase() === "INPUT") {
var value = e.target.value; // The value of the clicked radio button
}
});
That way, you don't have to worry about adding handlers dynamically; just do it once, after the quiz element is known to exist, and you can update its content all you want without having to worry about attaching handlers to the radio buttons within.
To do event delegation in general, you usually have to loop starting from e.target and going to its parentNode in order to find the element you're interested in (say you're interested in a div, but the click was on a span inside it); but of course, input elements can't have any elements inside them, so it's simple here.
You're probably wondering why the check on the tag name. If you associate your radio buttons with label elements (as is usually good practice), either by putting the input inside the label or using the for attribute on the label, you'll see two clicks when you click the label: One on the label itself, and a second one on the input that the label relates to. We're only interested in the one on the actual radio button.
Here's a simple example of the delegation above:
var quiz = document.getElementById("quiz");
quiz.addEventListener("click", function(e) {
if (e.target.tagName.toUpperCase() === "INPUT") {
var value = e.target.value; // The value of the clicked radio button
console.log("The value of that radio button is " + value);
}
});
for (var n = 0; n < 5; ++n) {
var div = document.createElement("div");
div.innerHTML = '<label><input type="radio" value="' + n + '" name="answer"> Radio ' + n + '</label>';
quiz.appendChild(div);
}
<div id="quiz"></div>
I'm having a little trouble adding an event listener to elements created dynamically.
I have a list of objects that represent matches a player plays in. And a for loop that iterates through them, creating 4 buttons for each match, a +1, a +2, a -1 and an END button.
However, even if they are well created, and appended where they should be, the event listeners are not kept. Here's a sample of my code:
var container = document.getElementById('container');
for (var i = 0; i < matches.length; i++) {
var row = document.createElement("div");
row.className = "row";
var plusOne = document.createElement("a");
plusOne.id = "plusone_ " + matches[i].id;
plusOne.addEventListener('click', function () {
alert('Clicked on plusOne!')
});
...
// adding plus two, minus one and END the same way
// however, END does have an eventListener on click
row.appendChild(plusOne);
container.appendChild(row);
}
If anyone has any idea why?
Working on the div's. I am doing changes that if one div is selected, it should deselect the another div.
The div's defined are in ul li
Like in every li, there is a div with same classname called as inonset. Now the div which is already selected is having a class of inonset isactive.
I am adding a onclick function on every <div class="inonset" onclick="selectme(divid)"> to select it and unselect other, but how the other will be unelected, I am lost
Here is the fiddle
Not have not added the javascript code yet, but from the code, it will clear what I am trying to do.
You will see initially one selected and others are there, i just trying to selected any other one and deselect the previous one, Hope my questions makes sense
Worst thing: I cannot use Jquery, Only Dojo or Plain Javascript
Update #1
<div class="optionsBox" align="left" id="Invoicing" onclick="chooseDiv(this);">
function chooseDiv(oObj){
var d = document.getElementsByClassName("ul li div");
alert(d.className);
It is giving me undefined and not looping over the classes
the div is having classes like
iv class="headerSelected isactive">
where isactive needs to be removed from the previous selected div and add to the newly selected Div
First u need to change on click event for this:
onclick="selectme(this)"
And then in function:
function selectme(oObj){
var d = document.getElementById("ul li div");
d.removeAttribute("class");
oObj.className = oObj.className + " otherclass";
}
It should work fine
I am not sure whether the answer is still required or not. However, posting my approach of doing it.
function removeClass(className) {
// convert the result to an Array object
var els = Array.prototype.slice.call(
document.getElementsByClassName(className)
);
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
el.className = el.className.replace(
new RegExp('(^|\\s+)' + className + '(\\s+|$)', 'g'),
'$1'
);
}
}
var elements = document.getElementsByClassName("inoneset");
for (var i = 0; i < elements.length; i++) {
(function(i) {
elements[i].onclick = function() {
removeClass("isactive");
//this.setAttribute("class", this.getAttribute("class") + " isactive");
var headerElem = this.getElementsByClassName("headerSelected")[0];
headerElem.setAttribute("class", headerElem.getAttribute("class") + " isactive");
var addressElem = this.getElementsByClassName("selDelAddress")[0];
addressElem.setAttribute("class", addressElem.getAttribute("class") + " isactive");
var footerElem = this.getElementsByClassName("footerSelected")[0];
footerElem.setAttribute("class", footerElem.getAttribute("class") + " isactive");
};
})(i);
}
Fiddle - http://jsfiddle.net/38nv5rft/18/
Reasoning
As you can see, there is a remove class function, that removes the class from the elements in the document. One can update it as per the requirement.
Then the main logic, which gets all the elements, iterate on them and bind the click function.
In click function, we are removing the inActive class from every element and then for current block, adding inActive class. Please note, as per the fiddle, I did not find the class on inoneset elements being updated, hence, commented out the code.
Important Point
Click event bubbles, hence, click on elements with showDelete and showDialog click functions will bubble the event to click event of inoneset i.e. click handler of inoneset will also be triggered. In order to stop the propagation of event to it, use event.stopPropogation() in showDelete and showDialog functions.
I just finished creating two buttons with an onclick event,
You can view the demo of the buttons here.
However, I need help with two issues which I'm not sure how I can solve.
Issue 1
As you can see in the demo, if you first click a button, a dropdown menu appears, but if you click on the second button while the first dropdown menu is visible, the second dropdown overlaps the first dropdown menu.
How can I close the dropdown when you click somewhere else on the page or on another button using javascript?
Issue 2
I want the button to look like this even if you hover over the button
And this is how it's going to look when you click the button and when the dropdown menu becomes visible. It should stay like this even if you don't have your mouse on the button or the dropdown menu.
How can I accomplish this with JavaScript?
Thanks in advance!
You just need to keep an array of your elements, when you set one to display, set the others not to.
var dropdowns = ['language', 'delivery-country'];
var elements = [];
var hideElements = function (dropdown) {
for (var i = 0, l = dropdowns.length; i < l; i++) {
if (dropdown !== dropdowns[i]) {
var div = document.getElementById(dropdowns[i] + '-dropdown');
div.style.display = '';
elements[i].className = 'inactive';
}
}
}
for (var i = 0, l = dropdowns.length; i < l; i++) {
elements[i] = document.getElementById(dropdowns[i] + '-icon');
(function (index) {
elements[index].onclick = function() {
var div = document.getElementById(dropdowns[index] + '-dropdown');
if (div.style.display !== '') {
div.style.display = '';
elements[index].className = 'inactive';
} else {
div.style.display = 'block';
elements[index].className = 'active';
}
hideElements(dropdowns[index]);
};
})(i);
}
For the second part of your question, add the respective classes in your html (inactive). The code above will toggle the classes, you just need to figure out the CSS. Start by removing the hover classes on the icons, and also use classes for the icons rather than ids which you need to specify for every element.
I have a table with a default of 4 rows for user to input. please see the fiddle here http://jsfiddle.net/xaKXM/4/
When the user click on "Add More", the table will add new row to the "labelTable" with unique ID, as well as "configtableTable".
var displaymore = '<tr id=row'+currentIndex+'><td style="text-align: center">'+currentIndex+'</td>'+
'<td width="60%"><p id="label_row_'+currentIndex+'"></p></td>'+
'<td><button type="button" class="switch" id="switch_'+currentIndex+'"data-role="button" data-transition="fade">Activate</button></td></tr>';
When button "Submit" is pressed, user can see the description and the "Activate" button in the configtableTable. In order to make sure the Activate button is useful, i append thisIndex to a paragraph #ptest. It works for the first 4 default rows but does not work for the newly added rows (5 onwards).
What's wrong with my logic and code?
SOLVED: by creating a class "switch" and use .on()
$("#configtableTable").on('click', ".switch", function () {
thisIndex= $('td:nth(0)',$(this).closest('tr')).text();
if(thisIndex == ""){thisIndex = 0;}
$('#ptest').append(thisIndex);
$.post('/request', {responseNumber:$('#number_'+thisIndex).val(), key_pressed:"activate"});
});
there are two errors
1.In the generated code for "addmore", it should be following code for button
id="switch_' + currentIndex + '"
2.After creating new buttons, you have to add the click event for them.
I suggest the following code
$('#configsubmit').click(function () {
for (var x = 1; x <= currentIndex; x++) {
$('#label_row_' + x).html($('#label_' + x).val());
}
$('#configtable').show();
$("#configeditdiv").show();
$('#labels').hide();
$("#configtableTable [id^='switch_']:button").unbind('click');
$("#configtableTable [id^='switch_']:button").click(function () {
thisIndex = $('td:nth(0)', $(this).closest('tr')).text();
if (thisIndex === "") {
thisIndex = 0;
}
$('#ptest').append(thisIndex);
$.post('/request', {
responseNumber: $('#number_' + thisIndex).val(),
key_pressed: "activate"
});
});