froI have a form with many inputs and I want to add a class to focused input label tag and remove class when another input selected.
I make such code
onInputSelected: function(e) {
var label = e.target.previousElementSibling;
label.classList.add('highlight');
}
but how can I remove class from one input and add to another when I change focus?
Updated:
I found solution but looks like it's to complicated :)
data: {
allInputs: document.getElementsByTagName('input')
},
methods: {
onInputSelected: function(e) {
e.target.previousElementSibling.classList.add('highlight');
[].forEach.call(this.allInputs, function (currentValue, index) {
if(currentValue.name == this.name) {
return;
}
currentValue.previousElementSibling.classList.remove('highlight');
}, e.target);
}
}
First of all you're not being very clear what you want to do.
2nd of all you have found solution so just clean up your code.
3rd of all I'd try using el.closest.
const input = document.getElementById('yourInput');
const label = input.closest("label");
// or if you want to add ids to labels
const label2 = input.closest("#yourLabel");
Link to docs
With this solution you will be little bit more save. Couse in yours, lets just imagine that somebody change HTML structure... Then very high risk your code stops working.
Related
function showQuestion(questionAndAnswers) {
const shuffledAnswers = _.shuffle(questionAndAnswers.answers);
questionTag.innerText = questionAndAnswers.question;
shuffledAnswers.forEach(({ text, correct }, i) => {
answerTag[i].innerText = text;
answerTag[i].dataset.correct = correct;
});
}
document.querySelectorAll(".answer").forEach((answer) => {
answer.addEventListener("click", (event) => {
if (event.target.dataset ) {
answer.style.border = "1.5px solid"
}
});
});
function nextQuestion() {
const nextIndex = currentQuestionIndex + 1;
if (nextIndex <= myQuestions.length - 1) {
showQuestion(myQuestions[nextIndex]);
currentQuestionIndex = nextIndex;
} else {
end.style.visibility = "visible";
nxt_question_btn.style.visibility = "hidden";
}
}
Basically, In this quiz app, I have 4 buttons for answers and once you click on one answer it makes the border black. The problem I am facing is that once I press the next question, it loads up another question with 4 different answers but one of the buttons will still have the border black. How do I get it to reset once I load up another question? and Extra question if it's okay, how can I only select one button at a time per question?
There is no 'reset' as there is no default, you will just have to manually undo what you did earlier, i.e to remove the border completely:
answer.style.border = "none";
To select each button individually, you will ave to give them each an ID, based of something like an iteration, instead of trying to select them by the shared class
that's a tough one, there is no easy answer without knowing what the previous style was, so it's good to store the previous value of the style in memory and reset the styles to the previous value after the next question has been loaded
// a variable declared somewhere in common scope
let prevBorder
// "backup" the old value when you want to mark the answer as "selected"
prevBorder = element.styles.border
// restore to the initial value when you want to reset the styles
element.styles.border = prevBorder
Maybe you are looking for css:initial property?
The initial CSS keyword applies the initial (or default) value of a property to an element. It can be applied to any CSS property. This includes the CSS shorthand all, with which initial can be used to restore all CSS properties to their initial state.
Or you could add class and use classList.toggle() to switch between them.
I don't have your html code and full code so can't help you fully, but this is an example that may help you implement to your code:
document.querySelectorAll('button').forEach(item => {
item.addEventListener('click', function() {
item.style.border = '10px solid black'
document.querySelectorAll('button').forEach(i => {
if (i != item)
i.style.border = "initial"
})
})
})
<button>Click</button>
<button>Click</button>
<button>Click</button>
<button>Click</button>
I am making a validation function which displays an appropriate messagge for patternMismatch.
So far it displays the messagge, but it's the same for all input types.
const inputs = document.querySelectorAll("input");
inputs.forEach(function(input){
input.addEventListener("blur", function() {
if (input.validity.patternMismatch) {
if (e_space) {
e_space.textContent = "This field can only contain letters from a-z.";
input.classList.add("b-r");
}
}
})
Now I am trying to display different messagges for different input types, but I can't seem to find a way to select a specific type.
I have tryed if(input.type["text"]), if(input.type.text) and if(input["type=text"] but no messagge gets displayed.
ie:
if(input.type["text"]){
if(input.validity.patternMismatch){
if(e_space){
e_space.textContent = "This field can only contain letters from a-z.";
input.classList.add("b-r");
}
input.classList.add("input-red");
}
}
Any help would be welcome. Thank you.
fiddle
Use .matches to check if the input being iterated over matches a particular selector - such as, if it has an attribute:
if (input.matches('[type="text"]')) {
what about:
if (input.type=="text") {
//Whatever
}
I was wondering if someone can help me please, I have a series of checkboxes that when clicked change the div background, activate 2 inputs and add a tick icon. My issue is that when one check box is checked the class .TickIco shows for all and so does the .disableToggle
How can i get it so that this only affects one .checkBG at a time and not all of them?
Hopefully this JSFiddle will help explain what I mean.
https://jsfiddle.net/jayjay89/xfg96we5/
thanks
$(".checkBG").click(function () {
var checked = $(this).is(':checked');
var location = $(this).parent().parent().parent();
if (checked) {
$(this).parent().parent().parent().addClass("activeformBlock");
$(".tickIco").show();
$(".disabletoggle").removeAttr("disabled");
} else {
$(this).parent().parent().parent().removeClass("activeformBlock");
$(".tickIco").hide();
$(".disabletoggle").attr('disabled', 'disabled');
}
});
thanks
you can use the context in which the selector will be looked.
You already have the location variable which is the parent context for one of your row
$(".checkBG").click(function () {
var checked = $(this).is(':checked');
var location = $(this).parent().parent().parent();
if (checked) {
$(this,location).parent().parent().parent().addClass("activeformBlock");
$(".tickIco",location).show();
$(".disabletoggle",location).removeAttr("disabled");
} else {
$(this,location).parent().parent().parent().removeClass("activeformBlock");
$(".tickIco",location).hide();
$(".disabletoggle",location).attr('disabled', 'disabled');
}
});
Your issue lies in the way you are selecting the .tickIco and .disabletoggle elements:
$(".tickIco").show();
$(".disabletoggle").removeAttr("disabled");
These jquery calls use selectors that match all classes of .tickIco and .disabletoggle.
Dirty solution (finds elements of the parent with matching classes using .find()):
$(this).parent().parent().parent().find(".tickIco").show();
$(this).parent().parent().parent().find('.disabletoggle').removeAttr("disabled")
Better solution:
jQuery selecter takes the context of your selection as a second argument so you can:
var context = $(this).parent().parent().parent();
$(".tickIco", context).show();
$('.disabletoggle', context).removeAttr("disabled")
I wonder if it's possible to change the input's color in runtime.
Here's my select (Webix ui.richselect): http://webix.com/snippet/c64f9b12
{
view:"richselect", label:"Status", options:[
{ id:1, value:"Done", $css:"done" },
{ id:2, value:"Processing", $css:"process" },
{ id:3, value:"On hold", $css:"on-hold" },
{ id:4, value:"Failed", $css:"failed" },
],
on:{
onChange:function(newV, oldV){
webix.message("Status changed to "+this.getList().getItem(newV).value)
}
}
}
Each $css key related to the CSS class that is applied to the item.
<style>
.webix_list_item.done {
background:#ddf7dd;
}
<!-- . . . -->
.webix_list_item.webix_selected {
color:black;
font-weight:bold
}
</style>
After changing the richselect's value, I need to set the background color of the newly selected item as the background color of the richselect.
In my opinion, it can be done through the onChange event, but I have no idea how exactly I can solve it.
Any suggestions? Thanks in advance.
Here is your solution:
http://webix.com/snippet/08e187a7
1) First, dynamically get the class name of the element clicked in order to fetch that element
var className = ".webix_list_item." + this.getList().getItem(newV).$css;
var element = document.querySelector(className);
2) Next, just get the computed background color of that element and set the same to the "newly selected" element.
document.querySelector(".webix_el_richselect .webix_inp_static").style.backgroundColor = window.getComputedStyle(element,null).getPropertyValue("background-color");
I have written it one line, you could may be create variables and break it into more statements. say something like -
var clicked_bgcolor = window.getComputedStyle(element,null).getPropertyValue("background-color");
document.querySelector(".webix_el_richselect .webix_inp_static").style.backgroundColor = clicked_bgcolor;
I prefer doing these 2 in one line though(above mentioned).
So your final onChange code would be :
on:{
onChange:function(newV, oldV){
webix.message("Status changed to "+this.getList().getItem(newV).value);
var className = ".webix_list_item." + this.getList().getItem(newV).$css;
var element = document.querySelector(className);
document.querySelector(".webix_el_richselect .webix_inp_static").style.backgroundColor = window.getComputedStyle(element,null).getPropertyValue("background-color");
}
}
Let me know if any issues.
PS: Try to use JQuery more often, you could avoid such lengthy complicated JavaScript statements.
Thanks #Nikhil for the answer, it helped me to apply my combo logic on the richselect in the webix way.
So, the difference was that in the combo i was applying the style on the input and it was working but for the richselect applying the style on input was wrong rather i have to apply on the .webix_inp_static .
1. CSS
In your style for each of your custom css on webix_list_item you have to also add css for .webix_inp_static as shown:
<style>
.done .webix_inp_static,.webix_list_item.done {
background:#ddf7dd;
}
</style>
2. onChange function
You have to removeCss on the oldV if existing and addCss on the newV as:
onChange:function(newV, oldV){
if(oldV) webix.html.removeCss(this.getNode(), this.getList().getItem(oldV).$css);
if(newV) webix.html.addCss(this.getNode(), this.getList().getItem(newV).$css);
}
Please check the snippet here.
I am very new to JavaScript. I am trying to update a div, which works fine before the add and remove class pieces are added. The problem is when I add the class I can't seem to get it to be removed when the when the next image is clicked. I have used a remove class option, but it doesn't seem to want to work.
Any help is appreciated. Here is the code:
$('[class^="question"]').on('click', function(e) {
e.preventDefault();
var numb = this.className.replace('question', '');
$('[id^="answer"]').hide();
$('.question*').removeClass('question*selected');
$('#answer' + numb).show();
$('.question' + numb).addClass('question' + numb + 'selected');
});
Here is a link to the Fiddle I am Playing with.
Thanks.
You can keep track of your added class by defining a global variable. I created a working example in CODEPEN.
$(document).ready(function() {
var appliedClass = "container1";
var classNo = 1;
$(".buttonCon").click(function() {
if ($(".container").hasClass(appliedClass)) {
$(".container").removeClass(appliedClass);
classNo++;
if (classNo > 4) {classNo = 1;}
appliedClass = "container" + classNo;
$(".container").addClass(appliedClass);
}
});
});
I have appliedClass variable which keeps tracking of the latest added class. Every time you click on the button with .buttonCon class, this variable will be updated to the new added class. Next time, first we remove the former class. Then we added the new one. The second if statement might not be needed in your case, but in my example, I needed it to keep looping through container1 to container4 classes.
You've set yourself up with a really difficult-to-work-with class structure -- this can be a lot easier than you're making it. Give each of your "question" links the class 'question' and the unique id "question1", "question2", etc. Same for the answer nodes: class "answer" and id "answer1", "answer2" etc.
Now you can easily access all question links with $('.question') or all answers with $('.answer'), and can use the IDs to identify individual nodes as needed:
$('.question').on('click', function(e) {
e.preventDefault();
var numb = this.id.replace('question', '');
var answerNode = $('#answer'+numb);
if (answerNode.hasClass('hide')) {
// the Q they clicked on is not yet visible
$('.answer').addClass('hide'); // hide all answers
answerNode.removeClass('hide'); // show the desired one
} else {
// the Q they clicked on is already visible, so toggle it back off
answerNode.addClass('hide');
}
});
http://jsfiddle.net/647dadtj/