JS trigger event when val() change - javascript

Q: How to trigger event when val is changed from onkey event?
Problem: When change one input, other will change value, but don't change css.
JsFiddle: http://jsfiddle.net/6Qnbh/
$('.stat').val(0);
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
}).trigger("change");
/**/
$('.stat').keyup(function () {
var val = $(this).val();
if (val > 0) {
var num = Math.abs(val) * -1;
} else {
var num = Math.abs(val) * 1;
}
$('input[data-id=' + $(this).attr("data-link") + ']').val(num);
});

On this line
$('input[data-id=' + $(this).attr("data-link") + ']').val(num);
Add .trigger("change"); to ensure the change event is triggered:
$('input[data-id=' + $(this).attr("data-link") + ']').val(num).trigger("change");
Fiddle:
http://jsfiddle.net/6Qnbh/4/

You need to trigger the change event after setting the value. See your updated fiddle
$(function () {
$('.stat').val(0);
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
}).trigger("change");
/**/
$('.stat').keyup(function () {
var val = $(this).val();
if (val > 0) {
var num = Math.abs(val) * -1;
} else {
var num = Math.abs(val) * 1;
}
// I have added the .trigger('change') part here
$('input[data-id=' + $(this).attr("data-link") + ']').val(num).trigger('change');
});
});

function test(){
$(".stat").each(function () {
var val = $(this).val();
if (val > 0) {
$(this).css("border", "1px solid #0f0");
} else if (val < 0) {
$(this).css("border", "1px solid #f00");
} else {
$(this).css("border", "1px solid #000");
}
})
}
and call the function on keyup
DEMO

In your code, $(this) refers to the currently changed jQuery object.
An easy solution is:
$(".stat").change(function () {
var val = $(this).val();
if (val > 0) {
$('.stat').css("border", "1px solid #0f0");
} else if (val < 0) {
$('.stat').css("border", "1px solid #f00");
} else {
$('.stat').css("border", "1px solid #000");
}
Edit: depending on what you want to happen, #Anton may have the effect you are looking for; I wasn't certain what you need.
As for the reason why the other input box doesn't change, the explanation is still the same.

Related

I need DRY validate function to make its shorter

I have a validation function were is some code is repeating, how I can make it more shorter.
function validated() {
if (user.value.length < 9) {
user.style.border = '1px solid red';
userError.style.display = 'block';
user.focus();
return false;
}
if (password.value.length < 9) {
password.style.border = '1px solid red';
passError.style.display = 'block';
password.focus();
return false;
}
}
function validateField(elt, errorElt, minLength) {
if (elt.value.length < minLength) {
elt.style.border = '1px solid red';
errorElt.style.display = 'block';
elt.focus();
return false;
}
return true;
}
function validated() {
return validateField(user, userError, 9) && validateField(password, passwordError, 9);
}

How to make a loop wait for an event listener?

I am trying to create a coin toss game where you set the number of games you want to play, and then choose head or tails for each iteration. But my for loop doesen't wait for the eventListener and the loop is over before the user even clicked once.
function play(){
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
}
function choice(e){
let random = Math.floor(Math.random() *2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
if (random == 0){
result.src = head.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
if (random == 1){
result.src = tails.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh(){
result.style.border = "none";
clicked.style.border = "none";
}
}
function wait(){
for (let i = 0; i < playAmount; i++){
console.log(i);
play();
}
}
wait();
Thank you in advance!
You can solve this problem without for loop.
Just take a variable count = 0 and flag = false at the starting .
Now just follow the program as under
var count = 0 , flag = true ;
flag&&head.addEventListener("click", choice);
flag&&tails.addEventListener("click", choice);
function choice(e){
if(count>=playAmount)flag=false;
else count++;
let random = Math.floor(Math.random() *2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
if (random == 0){
result.src = head.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
if (random == 1){
result.src = tails.src;
result.style.height = "100%";
if(result.src == clicked.src){
result.style.border = "3px solid green";
}
else{
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh(){
result.style.border = "none";
clicked.style.border = "none";
}
}
I hope this solves your problem .
Let us go through some key parts of your implementation(refer to my comments inline)
function play() {
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
//the above 2 lines add a click event listener to the two buttons,
//that is, whenever these 2 buttons are clicked,
//the function `choice` will be called
}
function choice(e) {
let random = Math.floor(Math.random() * 2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
//the above 2 lines remove the click event listener from the two buttons
//that is, now the function `choice` will not be called at button click
if (random == 0) {
result.src = head.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
if (random == 1) {
result.src = tails.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh() {
result.style.border = "none";
clicked.style.border = "none";
}
}
function wait() {
for (let i = 0; i < playAmount; i++) {
console.log(i);
play();
//calls the play function `playAmount` times
}
}
wait();
Now let us discuss the problems with this approach
Calling the play() function playAmount times from wait() (tries to) binds(adds) the click event listener to both the buttons playAmount times, but adding the same function n times as an event listener is same as adding it once, reference : addEventListener docs
once choice is called, you remove the event listeners from both the buttons (remember , the event listeners were only bound once in a loop in the wait() function),
now with no event listener bound on the buttons, the buttons wont register the event click anymore.
The below implementation should work for you:
let numberOfTurnsTaken = 0;
//add a global variable to count the turns taken
function play() {
head.addEventListener("click", choice);
tails.addEventListener("click", choice);
//bind the event listeners
}
function choice(e) {
numberOfTurnsTaken++;
//increment the turns
let random = Math.floor(Math.random() * 2);
console.log(random);
let clicked = e.target;
e.target.style.border = "3px solid green";
//remove the event listeners only when the turns are over and we are `handling` the last turn
if(numberOfTurnsTaken == playAmount){
head.removeEventListener("click", choice);
tails.removeEventListener("click", choice);
}
if (random == 0) {
result.src = head.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
if (random == 1) {
result.src = tails.src;
result.style.height = "100%";
if (result.src == clicked.src) {
result.style.border = "3px solid green";
} else {
result.style.border = "3px solid red";
}
}
setTimeout(refresh, 3000);
function refresh() {
result.style.border = "none";
clicked.style.border = "none";
}
}
//set things rolling by binding click event handlers on the buttons
play();
//the loop is no longer needed
//function wait() {
// for (let i = 0; i < playAmount; i++) {
// console.log(i);
// play();
// }
//}
//wait();

Regex not validating postal codes properly

I've been trying to validate USA and Canadian postal codes as I'm sending them through an api. However, I can't seem to get the regex to work. My validation is a bit messy but it should work nonetheless, I believe the regex is correct I just have the wrong logic? I would appreciate any help. Thanks.
function checkoutv2() {
var typepostal;
if (xcountry == 1) {
//canada
typepostal = "Canada";
} else if (xcountry == 2) {
//usa
var typepostal = "USA";
}
console.log(xcountry);
var xfirstname = document.getElementById("firstname").value;
var xlastname = document.getElementById("lastname").value;
var xemail = document.getElementById("email").value;
var xcity = document.getElementById("city").value;
var xaddress = document.getElementById("address").value;
var xpostal = document.getElementById("postal").value;
xpostal = xpostal.toString().trim();
var reg = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
var ca = new RegExp(/([ABCEGHJKLMNPRSTVXY]\d)([ABCEGHJKLMNPRSTVWXYZ]\d){2}/i);
var us = new RegExp("^\\d{5}(-{0,1}\\d{4})?$");
if (xfirstname == "" || xfirstname.length > 50) {
document.getElementById("firstname").style.border = "1px solid red";
} else if (xlastname == "" || xlastname.length > 50) {
document.getElementById("lastname").style.border = "1px solid red";
} else if (reg.test(xemail) == false || xemail.lenth > 100) {
document.getElementById("email").style.border = "1px solid red";
} else if (xcity == "" || xcity.length > 100) {
document.getElementById("city").style.border = "1px solid red";
} else if (xaddress == "" || xaddress.length > 100) {
document.getElementById("address").style.border = "1px solid red";
} else if (
typepostal == "Canada" &&
ca.test(xpostal.toString().replace(/\W+/g, "")) == false &&
xpostal.length >= 10
) {
console.log("postal is cad");
console.log(xpostal);
document.getElementById("postal").style.border = "1px solid red";
} else if (
typepostal == "USA" &&
xpostal.length > 10 &&
us.test(xpostal.toString()) == false
) {
console.log("postal is us");
document.getElementById("postal").style.border = "1px solid red";
} else {
checkout();
}
}

How can I handle this AJAX(?) bug?

So I have a bug,everytime i try to click on an element(Generated by an autocomplete function I made using jquery) I can access it only if i click in middle,however,if i use arrows & enter it works everytime . Any ideeas? My code is. Maybe i just don't see it but i am looking at it for a few hours
{literal}
$(document).ready(function() {
function autocomplete(inp) {
var currentFocus;
var arr =[];
inp.on("input", function(e) {
var a, b, i, val = this.value;
closeAllLists();
if (!val) { return false;}
currentFocus = -1;
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
this.parentNode.append(a);
$.ajax({
type:"POST",
url:"//",
dataType: 'json',
data: {user_id: __st.a, keyword: val},
success: function(products) {
if(products.length){
products.forEach(function (product, index) {
b = document.createElement("div");
var div_class = "bundle_autocomplete_item_"+index;
b.setAttribute("class", div_class);
b.innerHTML = '<span style="float: left; display: block; width: 20%;"><img src="' + product.image_url + '" alt="productImageSrc"></span><span class="autocomplete-title">' + product.title + '</span>';
$(b).on("click", function(e) {
closeAllLists();
window.location.href = 'https://'+Shopify.shop+'/products/'+product.handle;
});
a.appendChild(b);
});
}
}
});
});
inp.on("keydown", function(e) {
var x = document.getElementById(this.id + "autocomplete-list");
if (x) x = x.getElementsByTagName("div");
if (e.keyCode == 40) {
currentFocus++;
addActive(x);
} else if (e.keyCode == 38) { //up
currentFocus--;
addActive(x);
} else if (e.keyCode == 13) {
e.preventDefault();
if (currentFocus > -1) {
if (x) x[currentFocus].click();
}
}
});
function addActive(x) {
if (!x) return false;
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
x[currentFocus].classList.add("autocomplete-active");
}
function removeActive(x) {
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("autocomplete-active");
}
}
function closeAllLists(elmnt) {
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
}
var searchForms = $('form[action="/search"]').each(function() {
$('input[name="q"]').each(function() {
$(this).attr("autocomplete" , "off");
autocomplete($(this));
});
});
$('head').append('<style> .autocomplete {position: relative;display: inline-block;border:10px solid red;} .autocomplete-items {position: absolute;border: 1px solid #d4d4d4;border-bottom: none;border-top: none;z-index: 99;top: 100%;left:0;right: 0;overflow:hidden;white-space:nowrap;} .autocomplete-items div {padding: 7px ;cursor: pointer;background-color: #fff; border-bottom: 1px solid #d4d4d4;text-overflow:ellipsis; white-space:nowrap; overflow:hidden;}} .autocomplete-items div:hover {background-color: #e9e9e9;}.autocomplete-active {background-color: DodgerBlue !important; color: #ffffff;} .autocomplete-title{font-size:13px; margin-left:3px;</style>');});
{/literal}
I removed the url from the ajax call for personal reasons

Classes Not Working in Jquery

My class pointers will not work once they are clicked.I am trying to create a delete button ,but when I click on the class I need it does not work or do anything.The problem occurs at around line 143 in my code and is label with 'the problem' and right now it just says console.log but not even that will work. The createTable() function is where the class is created in the final td at the bottom of the Javascript if that helps any.Any help is appreciated with this!
var name;
var age;
var sex;
var person;
var flagOne;
var flagTwo;
var flagThree;
var array = [];
var rowIndex;
createTable();
/* Modal Scripts */
$('.left').click(function(){
name = $("#name").val('');
age = $("#age").val('');
sex = $("#sex").val('');
$('.form-row:first-child').css('border','0');
$('.form-row:nth-child(2)').css('border','0');
$('.form-row:nth-child(3)').css('border','0');
if($('td>a.delete').css('opacity') == 1){
$('.modal-wrapper').css('display','none');
}
else {
$('.modal-wrapper').css('display','block');
$('.modal').animate({
opacity:1,
marginTop:'-117px'
},500);
}
});
$('.fa-times').click(function(){
$('.modal-wrapper').css('display','none');
name = $("#name").val('');
age = $("#age").val('');
sex = $("#sex").val('');
$('.modal').animate({
opacity:0,
marginTop:'-250px'
});
});
$('.modal-background').click(function(){
$('.modal-wrapper').css('display','none');
name = $("#name").val('');
age = $("#age").val('');
sex = $("#sex").val('');
$('.modal').animate({
opacity:0,
marginTop:'-250px'
});
});
/* Validation */
$('#button').click(function(){
flagOne = false;
flagTwo = false;
flagThree = false;
name = $("#name").val();
age = $("#age").val();
sex = $("#sex").val();
if(name.match(/^([a-zA-Z]{2,15}\s[a-zA-z]{2,15})/)){
flagOne = true;
}
else {
flagOne = false;
}
if (age < 0 || age > 130 || isNaN(age) || age == '') {
flagTwo = false;
}
else {
flagTwo = true;
}
if (sex == "male" || sex == "Male" || sex == "female" || sex == "Female"){
flagThree = true;
}
else {
flagThree = false;
}
if(flagOne == false || flagTwo == false || flagThree == false){
if(flagOne==false){
$('.form-row:first-child').css('border','3px solid red');
}
else {
$('.form-row:first-child').css('border','0');
$('.form-row:first-child').css('border-bottom','3px solid red');
}
if(flagTwo == false){
$('.form-row:nth-child(2)').css('border-right','3px solid red');
$('.form-row:nth-child(2)').css('border-left','3px solid red');
}
else {
$('.form-row:nth-child(2)').css('border','0');
}
if(flagThree == false){
$('.form-row:nth-child(3)').css('border','3px solid red');
}
else {
$('.form-row:nth-child(3)').css('border','0');
$('.form-row:nth-child(3)').css('border-top','3px solid red');
}
}
else if(flagOne == true && flagTwo == true && flagThree == true) {
$('.modal-wrapper').css('display','none');
$('.modal').animate({
opacity:0,
marginTop:'-250px'
});
storeObject();
}
});
/* Delete Button */
$('.right').click(function(){
if($('td>a.delete').css('opacity') == 1){
$('td>a.delete').css('opacity','0');
}
else if($('td>a.delete').css('opacity') == 0){
$('td>a.delete').css('opacity','1');
}
});
/* THE PROBLEM */
$('.delete').click(function(){
console.log("heelo");
});
/* Array Creation */
function storeObject() {
function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
person = new Person(name,age,sex);
array.push(person);
testArray();
}
/* Test Array */
function testArray() {
if(array.length == 8){
createTable();
alert('Table Limit Reached!');
}
else if (array.length > 8){
array.pop();
alert('Too Many Rows!');
}
else {
createTable();
}
}
/* Table Creation */
function createTable() {
var table = "<table><tr><td>Name<span class='special'>▲</span></td><td>Age<span class='special'>▲</span></td><td>Sex</td></tr>";
for(var i=0;i < array.length;i++){
if (array.length > 0){
table += "<tr><td>" + array[i].name + "</td>";
table += "<td>" + array[i].age + "</td>";
table += "<td>" + array[i].sex + "<a class='delete'><i class='fa fa-trash-o' aria-hidden='true'></i></a></td></tr>";
}
}
table += "</table>";
document.getElementById("tablePrint").innerHTML = table;
}
Delegate events like below. This is needed since when the events are registered the HTML is not in DOM yet.
$(document).on("click", ".delete", function(){
console.log("heelo");
});
and similarly for other events as well.
use .on() method attaches event handlers to the currently selected set of elements in the jQuery object. As of jQuery 1.7, the .on() method provides all functionality required for attaching event handlers.
$( ".left" ).on( "click", function() {
console.log( $( this ).text() );
});
OR
$(document).on( "click",".left" function() {
console.log( $( this ).text() );
});
more detail :http://api.jquery.com/on/

Categories