Javascript .click() different for elements w/ same class - javascript

I'm pretty new to Javascript/Jquery and am implementing a real simple image carousel for practice and ran into a problem regarding Jquery's "click" method.
The code I currently have is as follows:
$(document.getElementsByClassName("traverse")).click(function() {
if(this.id = "left"){
if (current == 0) {
current = images.length-1;
}
else {
current -= 1;
}
}
else if(this.id = "right") {
if(current = images.length-1) {
current = 0;
}
else {
current += 1;
}
}
$(document.getElementById("image-view")).css("background-image", "url(" + images[current] + ")");
});
With this code there are no errors, but every time I click either the "#right" or "#left" button, they both run code as if "this.id = 'left'". While I understand I can simply separate the two and this will work fine, is there a way I can do it similar to what I have now where I'm applying this event to the class, but differentiating the behavior by the id?
Thanks!

Typo
== to compare
= to assign
Strict equal (===) Returns true if the operands are equal and of the
same type
if(this.id === "left"){
^
and better use
class selector
$('.traverse').click(function(){ .. });
Problem with your code
you are assign this.id = "left" every time in if condition so is condition is always true
if(this.id = "left"){

You're setting this.id to left by only using a single = sign. Try this:
$(document.getElementsByClassName("traverse")).click(function(event) {
if(event.target.id === "left"){
and so on.

Related

javascript if state function doesn't read boolean

My code work with resize function boolean change with width,
but my function contain if statement doesn't read the boolean,
what is problem with my code?
I used = ==, but I don't know how to use them exactly
var footerMenu = ['#about', '#help']
var slideSwitch = false
function slideDown(){
footerMenu.forEach(function(list){
$(list+' p').click(function(){
$(list+' ul').slideToggle(300)
})
})
}
function slideClear(){
for( let i = 0; i < footerMenu.length; i++){
$(footerMenu[i]+' p').click(function(){
var choice = footerMenu[i]
footerMenu.splice(i, 1);
footerMenu.forEach(function(list){
$(list+' ul').slideUp(300)
})
footerMenu.splice(i, 0, choice);
})
}
}
function slideTotal(){
if(slideSwitch = true){
slideDown()
slideClear()
}
}
$(document).ready(function() {
checkWidth();
});
$(window).resize(function(){
checkWidth();
});
function checkWidth(){
$vWidth = $(window).width();
if($vWidth <576){
console.log("Width: Less than 576");
slideSwitch = true
}else{
console.log("Width: More than 576");
slideSwitch = false
}
}
slideTotal()
I hope correct my code, if I don't have any wrong please advice me how to solve it
= is the assignment operator. It changes the value of what is on the left hand side. It is usually not what you want in an if statement unless you really know what you are doing.
== and === are the comparison operators. The different between them is that == automatically converts the two arguments to the same type, whereas === does not. But that doesn't really matter, my advice is to always use === to compare variables in an if statement.
Also, comparing to true (x === true) is completely pointless because that is what an if statement already does; it is unnecessary.
(side note: you could do if (x === true === true === true), and that would be the same as if (x).)
The code you want is:
function slideTotal() {
if (slideSwitch) {
slideDown();
slideClear();
}
}
Well, to start:
function slideTotal(){
if(slideSwitch = true){
slideDown()
slideClear()
}
}
change: slideSwitch = true
to: slideSwitch == true

addEventListener (and removeEventListener) function that need param

I need to add some listeners to 8 object (palms).
These object are identical but the behaviour have to change basing to their position.
I have the follow (ugly) code:
root.palmsStatus = ["B","B","B","B","B","B","B","B"];
if (root.palmsStatus[0] !== "N")
root.game.palms.palm1.addEventListener("click", palmHandler = function(){ palmShakeHandler(1); });
if (root.palmsStatus[1] !== "N")
root.game.palms.palm2.addEventListener("click", palmHandler = function(){ palmShakeHandler(2); });
if (root.palmsStatus[2] !== "N")
root.game.palms.palm3.addEventListener("click", function(){ palmShakeHandler(3); });
if (root.palmsStatus[3] !== "N")
root.game.palms.palm4.addEventListener("click", function(){ palmShakeHandler(4); });
if (root.palmsStatus[4] !== "N")
root.game.palms.palm5.addEventListener("click", function(){ palmShakeHandler(5); });
if (root.palmsStatus[5] !== "N")
root.game.palms.palm6.addEventListener("click", function(){ palmShakeHandler(6); });
if (root.palmsStatus[6] !== "N")
root.game.palms.palm7.addEventListener("click", function(){ palmShakeHandler(7); });
if (root.palmsStatus[7] !== "N")
root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });
I have two needs:
1) doesn't use an anonymous function on click event.
I wrote this code, but it doesn't work
root.game.palms.palm8.addEventListener("click", palmShakeHandler(8));
So this one works fine
root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });
But I didn't understand how remove the event listener.
I try this solution, but it doesn't work
root.game.palms.palm8.addEventListener("click", palmHandler = function(){ palmShakeHandler(8); });
root.game.palms.palm8.removeEventListener("click", palmHandler);
2) add and remove listener in a for cycle
I wrote the follow code but the behaviour is not correct.
for (i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", function(){ palmShakeHandler(i); });
}
}
the listeners was added but the value of the parameter passed to the palmShakeHandler is always 8.
Nobody could help me to fix these issues?
There is a actually, a perfect way to do that in JavaScript using the Function.prototype.bind method.
bind let you define extra parameters that will be passed, as arguments, of the function.
You should also keep in mind that bind creates a new function and doesn't modify the initial function.
Here is what it looks like:
function palmHandler(number) {
// your code working with `number`
}
var palmHandler8 = palmHandler.bind(null, 8)
// the palmHandler8 is now tied to the value 8.
// the first argument (here null) define what `this` is bound to in this function
This should fix your problem, and you will be able to remove handlers easily :)
Your code will look like this:
for (i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", palmShakeHandler.bind(null, i));
}
}
To be able to remove the handler afterward, you need to keep a reference to the function you create with bind. This would be the way to do this.
var boundHandler = handler.bind(null, i);
element.addEventListener(boundHandler);
element.removeEventListener(bounderHander);
If you want to know more about the awesome bind method in JavaScript, the MDN is your friend :) https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
BTW, the problem with you function always returning 8 is a very common question in JavaScript. This thread will explain everything (spoiler, it's a matter of scoping :) ) https://stackoverflow.com/a/750506/2745879
So in case your array of »palms« is very huge, it is basically a bad Idea to add a single event listener to each of them, because that causes performance flaws. So I would suggest a different approach:
var handlers = [function (e) {}, …, function (e) {}];
root.game.palms.forEach(functiion (palm, idx) {
palm.setAttribute('data-idx', idx);
});
<palmsparent>.addEventListener('click', function (e) {
var c = e.target, idx = -1;
while (c) {
if (c.hasAttribute && c.hasAttribute('data-idx')) {
idx = parseInt(c.getAttribute('data-idx'));
break;
}
c = c.parentNode;
}
//here you also check for the »palm status«
if (idx >= 0) {
handlers[idx](c);
}
})
One event listener for all, much easier to remove and better for performance.
In your last solution you are pasing the same var to every function and that is what make al the functions work with 8 because is the last value of the variable.
To work arround that you can use "let" ( please at least use var, otherside that "i" is global and can be changed every where in the code) but since I dont know wich browser you target I propose other solution.
for (var i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", (function(index)
(return function(){
palmShakeHandler(index);
}))(i);
}
}
Since its look like You are targeting modern browsers I will use let.https://kangax.github.io/compat-table/es6/
for (var i=1; i <= root.palmsStatus.length; i++){
let index = i;
let intermediateFunction = function(){palmShakeHandler(index);};
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click",intermediateFunction);
root.game.palms["palm" + i].removeHandShake = function(){this.removeEventListener("click",intermediateFunction)};
}
}
So now you just need to call "removeHandShake" and will remove the listener,
I have code this right here so it ease some minor errors to pop

having problems returning value from functions

Hello Im having problems returning a value from the AmountToDisplay() function I feel like a module approach would be appropriate but since I'm new to OOP I've been having problems setting that up
function AmountToDisplay(){
$emitter = $({});
$('#amountItems').change(function(){
var amountchosen = $("#amountItems option:selected").val();
$emitter.trigger('amountUpdate', amountchosen);
});
$emitter.on('amountUpdate', function(e, val){
if(val == 2){
return 2;
}else if(val == 3){
return 3;
}else if(val == 4){
return 4;
}
})
}
I want to be able to do something like
if(AmountToDisplay() ==2){
..append 2 items to body
}else if(AmountToDisplay() ==3){
..append 3 items to body
}
console.log(AmountToDisplay()) gives undefined
instead of returning and I use the alert method alert(2), it works. I'm trying to get the values out of the select box so I could decouple separate the value from the event so I could use the value in other part of my code other parts in my code in this jsfiddle. Thanks in advance for your help.
EDIT THE thing is I want to be able to use the amount somewhere out of the change event. so if the user clicked 3 I want to be able to have that value so I could perform another function not related to the change event even though the value changes when the user inputs. pub/sub?
Try going through the backdoor. use arguments to cheat in the variable you want.
$emitter.on('amountUpdate', function(e, val){
console.log(arguments);
if(val == 2){
return 2;
}else if(val == 3){
return 3;
}else if(val == 4){
return 4;
}
})
you can see the variable you want is in arguments[1]
Also returning anything here doesn't serve a function. it does literally nothing.
You would need to pass it to an event handler.
so by modifying your code like this:
$emitter.on('amountUpdate', function(e, val){
val = arguments[1];
if(val == 2){
myEventHandlerfor2(val,e);
}else if(val == 3){
myEventHandlerfor3(val,e);
}else if(val == 4){
myEventHandlerfor4(val,e);
}
})
edit for showing how to put it in an object
function FruitBasket() {
this.apples = 0;
this.pears = 0;
this.bananas = 0;
this.iwonteatthat = 0;
}
FruitBasket.prototype.addFruit = function(which) {
switch(which) {
case 0 : this.apples++;break;
case 1 : this.pears++;break;
case 2 : this.bananas++;break;
case 0 : this.iwonteathat++;break;
}
}
FruitBasket.prototype.registerManipulator = function(manipulator) {
if(!(manipulator instanceof jQuery)) {
manipulator = $(manipulator);
}
manipulator.on('amountUpdate', jQuery.proxy(function(e, val){
val = arguments[1];
this.addFruit(val);
},this);
}
myFruitBasket = new FruitBasket();
myFruitBasket.registerManipulator($('#formfieldstuff'));
myFruitBasket.registerManipulator(document.getElementById('OtherManipulator'));
The return that do you have only exits the function of the event, but not the function AmountToDisplay.
The event must be outside the function
The function only need to return the value of the select with amountItems
The console.log or your logic must be inside the event
http://jsfiddle.net/mdf083Lb/2/
function AmountToDisplay(){
return $("#amountItems option:selected").val();
}
$("select").change(function(){
console.log(AmountToDisplay());
});
You don't need to defina an event method or something else, you can get selected value of select box where ever you want by using jquery selector :
var amountToDisplay = $("#amountItems option:selected").val();

How can I detect a jquery Fade animation is in process or not?

Here is the code about jQuery fadeIn fadeOut
function timecheck(obj,options,inAction){
var items = options.items;
// check if anything needs to be done
for (var i=0; i<items.length; i++) {
if(items[i][0]> obj.get(0).currentTime) {
$('#item_'+i).hide();
}else if(items[i][0]<=obj.get(0).currentTime && items[i][1] >= obj.get(0).currentTime && !inAction['item_'+i]){
console.log(inAction['item_'+i] = true);
$('#item_'+i).fadeIn('normal',function(){ inAction['item_'+i] = false; console.log(inAction); });
}else if(!inAction['item_'+i]){
console.log(inAction['item_'+i] = true);
$('#item_'+i).fadeOut('normal',function(){ inAction['item_'+i] = false; console.log(inAction); });
}
}
This code call by javascript every 40ms. my problem is callbacks try to set false incorrect inAction elements. How can i provide that?
For loops continue increasing. You need a closure and since you're using jQuery already, here is an option:
function timecheck(obj, options, inAction) {
var items = options.items;
// check if anything needs to be done
$.each(items, function(i) {
if (items[i][0] > obj.get(0).currentTime) {
$('#item_' + i).hide();
} else if (items[i][0] <= obj.get(0).currentTime && items[i][1] >= obj.get(0).currentTime && !inAction['item_' + i]) {
console.log(inAction['item_' + i] = true);
$('#item_' + i).fadeIn('normal', function () {
inAction['item_' + i] = false;
console.log(inAction);
});
} else if (!inAction['item_' + i]) {
console.log(inAction['item_' + i] = true);
$('#item_' + i).fadeOut('normal', function () {
inAction['item_' + i] = false;
console.log(inAction);
});
}
});
}
Otherwise, what is happening is that when the callback is called, it's already at the i already equals items.length
You can use the jQuery animation queues. Simply pass a string representing the name of your animation queue to the animating functions (hide, fadeIn, fadeOut, ...). For example, use your hide function like :
$('#item_'+i).hide({queue: "queueName"});
Then simply retrieve the number of animations left in your animation queue using :
$('.#item_'+i).queue("queueName").length;
You can intermittently check the value of length using window.setInterval and then apply your logic when the length property reaches 0.
See jQuery documentation for details :
queue
animate (same thing for hide(), fadeIn() and fadeOut())

Javascript if clause won't work

I'm having trouble with a javascript function that needs to take a global variable into account.
It's kind of a control mechanism I would like to implement, but I can't seem to get it right.
Here's the relevant code
<script type="text/javascript">
var active = 0;
function SetEndTime(lngOpenPersonID,lngToDoID){
if(active = 0){
alert('Time has been stopped');
}
else{
var strURL = 'blabla';
CallAJAXURL(strURL);
}
active = 0;
}
function SetStartTime(lngToDoID,lngToDoItemID,bitCountsForTotal){
if(active = 1){
alert('Time has been started');
}
else{
var strURL = 'blabla';
CallAJAXURL(strURL);
}
active = 1;
}
When I call SetStartTime without doing anything else, I always get the alert. Is there something wrong with my syntax?
if (active == 0) {
You need 2 "=" characters to make a comparison operator. There's also === which performs an equality comparison without type promotion.
Your code is syntactically correct because an assignment operation is a valid expression. The first if statement you had:
if (active = 0) {
will never be true, because the value of the expression is always zero. The second one:
if (active = 1) {
conversely is always true because the value is always one.
its not (alert = 1) .. its ( alert == 1 ).. your condition says its always true -- your assigning alert to 1

Categories

Resources