Prevent Looping in jQuery Advanced News Ticker (Forking/Modifying) - javascript

I realize this question is rather niche and should be directed at the author on github or otherwise.
But, the plug-in has not been updated in over 5 years, and, being a relatively straight forward plug-in, I"m trying to modify it so that it prevents it from looping elements when Previous or Next is clicked.
See here for a working example:
https://jsfiddle.net/zwb1vr96/2/
As you can see, hitting the Previous button while it is on 1 brings it to 3.
Similarly, if it's on 3 and you click Next, it loops back to 1.
As seen in the fiddle, I gave a length variable (var listlength = $("#newsticker li").length;) inside the plug-in function which tells me how many list (or li) items are in my list.
The next modification must be within these lines:
if(this.options.nextButton && typeof(this.options.nextButton[0]) !== 'undefined')
this.options.nextButton.click(function(e) {
this.moveNext();
this.resetInterval();
}.bind(this));
if(this.options.prevButton && typeof(this.options.prevButton[0]) !== 'undefined')
this.options.prevButton.click(function(e) {
this.movePrev();
this.resetInterval();
}.bind(this));
But I am kept up on the fact that this plug-in works by defining a set height and doesn't modify unseen li items.
Here's what I'm trying:
adding a var count = 0;
and to the next button
this.options.nextButton.click(function(e) {
if (count == 3) { return false; }
else { count++; }
as well as to the previous button
this.options.prevButton.click(function(e) {
if (count == 0) { return false; }
else { count--; }
It works to an extent-- but is still buggy and is not giving the proper count to return false on.
JsFiddle Attempt
How can I create a variable within these Previous and Next script functions above to know which list item it is currently on (in the jsfiddle example - 1, 2, or 3) and subsequently prevent the event from firing if my list item is on 1 when the Previous button is clicked as well as prevent the firing of the Next button if the list item being shown is at 3 (hence preventing the looping feature as described above).

Your problem is, that the ticker has no option to prevent the constant auto-removal/appending of ticker items as it animates:
you might consider this alternative plugin that has an option of autoAppend which you could set to false, then I would expect that the ticker stops at the end without looping (also if you manually control it).

Well I did find a solution -- it seems rather basic but it does function at least in my limited example:
https://jsfiddle.net/8fcz9470/5/
new variables in js function
var listlength = $("#newsticker li").length;
var count = 1;
And them modifying the Next Button
this.options.nextButton.click(function(e) {
if (count == 3) {
alert(count);
return false;
}
else if (count < 3) {
count++;
alert(count);
this.moveNext();
this.resetInterval();
}
}.bind(this));
And Previous button
this.options.prevButton.click(function(e) {
if (count == 1) { alert(count); return false; }
else if (count > 0) {
count--;
alert(count);
this.movePrev();
this.resetInterval();
}
}.bind(this));
If anyone sees any potential issues with this method, feel free to chime in with a better answer (as like I said, it does seem rather basic)! Thanks.
edit:
Actually, for dynamic variables, this seems to be working within the js code:
. . . . .
Plugin.prototype = {
init: function() {
var count = 1;
var listlength = $("li").length;
. . . . .
. . . . .
. . . . .
. . . . .
if (this.options.nextButton && typeof(this.options.nextButton[0]) !== 'undefined')
this.options.nextButton.click(function(e) {
if (count == listlength) {
return false;
} else if (count < listlength) {
count++;
this.moveNext();
this.resetInterval();
}
}.bind(this));
if (this.options.prevButton && typeof(this.options.prevButton[0]) !== 'undefined')
this.options.prevButton.click(function(e) {
if (count == 1) {
return false;
} else if (count > 0) {
count--;
this.movePrev();
this.resetInterval();
}
}.bind(this));

Related

Why doesn't the removeChild remove the element?

I have written this scrip to take out ads on a website. Was working on it the whole day.
This is the JS code:
var timer = setInterval(deletor, 1);
function deletor() {
timer;
var slider = document.querySelector("#slider-con");
var bannerTop = document.querySelector("#MainContent > div:nth-child(2)")
var bannerMiddle = document.querySelector("#MainContent > iframe");
var bannerRandom = document.querySelector("#MainContent > div:nth-child(7)");
var bannerRandom2 = document.querySelector("#MainContent > div:nth-child(6)");
if (slider == undefined) {
return false;
} else {
slider.parentNode.removeChild(slider);
};
if (bannerTop == undefined) {
return false;
} else {
bannerTop.parentNode.removeChild(bannerTop);
};
if (bannerMiddle == undefined) {
return false;
} else {
bannerMiddle.parentNode.removeChild(bannerMiddle);
};
if (bannerRandom == undefined) {
return false;
} else {
bannerRandom.parentNode.removeChild(bannerRandom);
};
if (bannerRandom2 == undefined) {
return false;
} else {
bannerRandom2.parentNode.removeChild(bannerRandom2);
};
};
Now, as you can see, it gets the values first and then goes through if statements. Idea behind this is: On first try, it deletes the elements and on the second one, it stops the function.
But when I inserted this last element, it won't delete it. The ID is correct, everything is correct but it won't delete the element, so I keep getting the same alert over and over.
Also, I found out that, I get this banner ad on two places. When I have "var bannerRandom = document.querySelector("#MainContent > div:nth-child(7)");" this, it appears as "document.querySelector("#MainContent > div:nth-child(6)")" this, and when I have both, it appears as "document.querySelector("#MainContent > div:nth-child(6)")" this. And it's not deleted.
Console shows no errors.
Your various statements in the form:
if (slider == undefined) {
return false;
} else {
slider.parentNode.removeChild(slider);
};
mean this: "If slider wasn't found in the DOM, exit the function. Otherwise, remove the slider and continue the function."
So that means your function will terminate the first time one of the elements you're looking for doesn't exist. Since it terminates then, none of the other elements after it is checked. That seems unlikely to be what you want to do.
You probably just wanted:
if (slider) {
slider.parentNode.removeChild(slider);
}
...and so on.
Note that you don't put ; at the end of a block attached to a flow-control statement like if or else, which is why I've removed it above. (Doing so is harmless, because JavaScript ignores them; but it's pointless.)

Adding to local storage only working after refreshing the page after button navigation to another page

I am developing an app that allows user to search for fishing lakes in their area. To do this they can type in their location which then displays fisheries near them that i have identified in the Json data. The search works perfectly with the code below i have written (i know it maybe a little flaky as i am not the best programmer).
//search
$(document).ready(function(){
$('#exampleSearch').keyup(function() {
var searchVal = $('#exampleSearch').val();
$('#results').empty();
console.log(searchVal);
var results = [];
$.getJSON("/data/locations.json",function(locations) {
for (var i = 0; i < locations.length; i++) {
if (locations[i].location.match(searchVal)) {
results.push(locations[i]);
}
}
$.each(results, function(index,result) {
var $resultsLi = $(
'<div class="row">'+
'<div class="twelve columns profile-information ">'+
'<div class="profile-title">'+
'<h6>'+result.name+'</h6>'+
'</div> ' +
' <img class= "favourites-pic" src="'+ result.image +'" alt="Fishery">'+
'<a class="view" href="'+ result.url + '" >View</a>'+
'</div>'+
' </div>'
)
$("#results").append($resultsLi);
});
});
});
});
I have now added a feature where users can now add their search results to their favourites page, by click a Add to favorites button on the page of the fishery they found from their search with the following code:
Javascript:
//Add to Favourites
$(function() {
$( ".addFavourites" ).on("click", function() {
try {
$(this).attr('disabled', true);
var locIdToAdd = $(this).closest("p").attr("id");
var myFavouriteLoc=JSON.parse(localStorage.getItem("favLoc"));
if (myFavouriteLoc == null) {
myFavouriteLoc = [];
}
if (myFavouriteLoc != null) {
for ( var j = 0; j < myFavouriteLoc.length; j++) {
if ( locIdToAdd == myFavouriteLoc[j]) {
alert("This property is already in your favourites");
myFavouriteLoc = [];
}
}
}
myFavouriteLoc.push(locIdToAdd);
localStorage.setItem("favLoc", JSON.stringify(myFavouriteLoc));
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
console.log("Error: Local storage limit exceeds");
} else {
console.log("ERROR: Saving to local storge.");
}
}
});
});
Html:
<p id="loc 1">
<input class="button-primary green addFavourites" type="submit" value="Add to Favourites">
</p>
THE PROBLEM
Upon clicking the 'view' button on the search page results, and navigating to a fishery page. I have a problem where i have to then refresh the page again before the add to favourites button will add anything to the local storage, it is clickable, but nothing happens. once i refresh the page it works fine.
Can anyone help with why i have to refresh the page first? any help is a appreciated :)
Try this jquery code to add favorites, it should work on each click:
$( document ).on("click", ".addFavourites", function(e) {
e.preventDefault();
try {
$(this).attr('disabled', true);
var locIdToAdd = $(this).closest("p").attr("id");
var myFavouriteLoc=JSON.parse(localStorage.getItem("favLoc"));
if (myFavouriteLoc == null) {
myFavouriteLoc = [];
}
if (myFavouriteLoc != null) {
for ( var j = 0; j < myFavouriteLoc.length; j++) {
if ( locIdToAdd == myFavouriteLoc[j]) {
alert("This property is already in your favourites");
myFavouriteLoc = [];
}
}
}
myFavouriteLoc.push(locIdToAdd);
localStorage.setItem("favLoc", JSON.stringify(myFavouriteLoc));
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
console.log("Error: Local storage limit exceeds");
} else {
console.log("ERROR: Saving to local storge.");
}
}
});
Just make sure you are not putting this jquery function inside $(document).ready(function(){}) or $(function(){}) because it is not required
I can't see any code relating to loading the list of favourites, but I think it's fair to assume to that when the page loads you're loading the items from storage and placing them in, and then the pages where you add favourites and view favourites don't involve any loading between them. Therefore, of course, loading the items for the favourites list will only be performed on load, and so placing new items into the localStorage without reloading will not add them. So I'm going to cover a few things.
Firstly, don't use == and !=. They perform type coercion, (numbers to strings, strings to numbers, null to undefined, etc.), the rules for which are unintuitive and unmemorable and are best simply avoided, lest they cause difficult to diagnose problems in your code. Use === and !== instead, these behave just like == and != does in other languages. If you want to perform type coercion I'd do so explicitly (e.g. Number('5')).
Secondly, and just as a suggestion, if you implement the local storage as an object, you won't need to loop and can simply use property names. So you can replace
if (myFavouriteLoc != null) {
for ( var j = 0; j < myFavouriteLoc.length; j++) {
if ( locIdToAdd == myFavouriteLoc[j]) {
With simply
if (myFavouriteLoc && myFavouriteLoc[locIdToAdd]) {
// ...
}
The object && object.property idiom will perform a truthy check on both the object and the property, only passing if they are both truthy (not falsy). Here's a list of falsy values.
So, to answer your actual question. I'd say you have two options:
Reload the page on each addition, or
AJAXily add the entry to your views when favourites are added. Favourites will then, of course, need be removed
Going with my assumption in the first paragraph, I'd say that the second option is your best bet, as the constant page refreshes would provide a bad user experience.
So here's the jsfiddle
(function bindBtns() {
$('.Table-btn--add').click(function () {
addBinding($(this));
});
$('.Table-btn--remove').click(function () {
removeBinding($(this));
});
})();
Here is an immediately invoked function, meaning it's run straight away. This will bind the existing buttons' behaviour, depending on whether they are add or remove buttons.
function addBinding($btn) {
$btn.parent()
.detach()
.appendTo($('#favourites'));
// add to local storage here
modifyAttributes($btn);
}
Here's the behaviour for the binding, fairly straight forward, but:
Select the buttons parent, i.e. the row
Detach it from the DOM, i.e. the current table
Attach it to the other table
Rebind the button to perform the opposite behaviour, shown below
Place your behaviour for adding or removing from local storage where I've placed the comments.
removeBinding is exactly the same except it appends to the other table.
function modifyAttributes($btn) {
if ($btn.hasClass('Table-btn--add')) {
$btn.text('Remove')
.removeClass('Table-btn--add')
.addClass('Table-btn--remove')
.off('click')
.click(removeBinding.bind(null, $btn));
} else if ($btn.hasClass('Table-btn--remove')) {
$btn.text('Add')
.removeClass('Table-btn--remove')
.addClass('Table-btn--add')
.off('click')
.click(addBinding.bind(null, $btn));
}
}
Split on whether this is an adding button, or a removing button. (The next steps will be for both versions.)
Update the text to be the opposite, (add -> remove, remove -> add)
Remove the current class
Add the new class
Remove the old click binding
Bind the new click binding. Read about .bind here
In your version you would replace .Table-btn--add with .addFavourites, and place addBinding($(this)) in your try block, and then you can just copy over the other functiona verbatim (I think).
Good luck! Sorry that got so long, and let me know how it goes.

Jquery keydown only works once

EDIT: I solved it by changing = to ==, but that didnt fully solve it but then I added a change to $currentSlide and now it works! Yay!
$(document).keydown(function(e) {
if(e.keyCode == 39)
{
if($currentSlide == $slide1){
slideShow(slide2);
$currentSlide = $slide2;
}
else if($currentSlide == $slide2){
slideShow(slide3);
$currentSlide = $slide3;
}
else if($currentSlide == $slide3){
slideShow(slide1);
$currentSlide = $slide1;
}
}
})
I have searched for an answer but haven't found anything that suits my question. I am a noob on javascript so bear with me.
I have a function that works as a slideshow. (I use $ in front of my jquery variables, I have a lot of javascript variables too so I just use it to separate them.)
var $currentSlide = "#slide1";
var $slide1 = "#slide1";
var $slide2 = "#slide2";
var $slide3 = "#slide3";
function slideShow($slide) {
if ($slide != $currentSlide){
$($currentSlide).fadeOut(500);
$($slide).delay(500).fadeIn(500);
$currentSlide = $slide;
}
};
To call this function, I use a simple link with parameter depending on which slide is active.
onclick="slideShow(slide2)"
And then I want to change slide with keypress (to right). This is my code for the keypress:
$(document).keydown(function(e) {
if(e.keyCode == 39) {
if ($currentSlide = $slide1){
slideShow(slide2);
} else if($currentSlide = $slide2) {
slideShow(slide3);
} else if($currentSlide = $slide3) {
slideShow(slide1);
}
}
})
It works perfectly when using the links but when I press key it behaves very weird. First click works like a charm, but then it doesnt work any more. If I click to get the third slide, another click will put next slide on top of slide3 but slide3 never goes away.
I realise there is some huge mistake by me here but I'm too much of a beginner to fix it. Any ideas?
your if-else conditions will always be true, because you used '=' instead of '=='. since your first if condition will be true it always shows slide2 and it looks to you that it only worked once
$(document).keydown(function(e) {
if(e.keyCode == 39) {
if ($currentSlide == $slide1){
slideShow(slide2);
} else if($currentSlide == $slide2) {
slideShow(slide3);
} else if($currentSlide == $slide3) {
slideShow(slide1);
}
}
})
The second problem maybe caused by the clock on the slideshow, if you are using one. When you click the next/previous button you need to reset the clock of your slideshow.
There are two issues
You do an assignment in your if conditions, so they always are true. Instead use the comparator ===;
In the onclick attribute you specify an undefined variable, since the $ is missing from it
Beside correcting this, I would suggest to use a class for your slide elements, not individual IDs. So use class="slide" instead of id="slide1" in your HTML, and apply it to all slides -- they can share the same class.
Then store the sequence number of the current slide, counting from 0.
I would also remove all the onclick attributes on the slide elements and deal with click handlers from code, which can be done quite concisely with $('.slide').click( ... ):
var currentSlideNo = 0; // zero-indexed
function slideShow(slideNo) {
if(slideNo != currentSlideNo){
$('.slide').get(currentSlideNo).fadeOut(500);
currentSlideNo = slideNo;
$('.slide').get(currentSlideNo).delay(500).fadeIn(500);
}
};
$('.slide').click(function () {
slideShow((currentSlideNo + 1) % $('.slide').length);
});
$(document).keydown(function(e) {
if (e.keyCode == 39) {
slideShow((currentSlideNo + 1) % $('.slide').length);
}
});

Display Based on innerHtml number

I want to create a system that displays certain content based on the number for this innerhtml content...
Here's the actual element itself, 17 is just the number for mine it is different for each user:
<span id="your_div_id_diamonds"><dd><div class="field_uneditable">17</div></dd></span>
I want it to display if their number is say between 10 and 20... Here's a code I've been trying to work with, but it only does one number at a time and currently isn't working...
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML = "17") {
document.getElementById('elitecontent').className="gotelite";
}
else {
document.getElementById('elitecontent').style.display="none";
}
}
});
Here's a version that works, but again only works for one number at a time... It'd be a huge pain if I had it go up to say 150 or 200, I'd have to make like 200 else if statements.
$( "#lev1" ).load('/u' + _userdata.user_id + ' #field_id-14 dd', function() {
var divs= document.getElementsByClassName('field_uneditable');
for (var i = 0, len = divs.length; i < len; ++i) {
if(divs[i].innerHTML.indexOf("7") != 1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else if(divs[i].innerHTML.indexOf("16") != -1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else if(divs[i].innerHTML.indexOf("17") != -1) {
document.getElementById('elitecontent').innerHTML="Elite";
}
else {
document.getElementById('elitecontent').innerHTML="Starter";
}
}
});
I basically want a code that works similar to with values, where I can just put something like >=10 and =<20
The problem you are facing with your current code is that you aren't using the correct comparison statements = is declarative, not used for comparison. In its place you should be using ==(matches regardless of data type) or === (must match data type as well) for instance
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML = "17") {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
should be
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML == "17") {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
However, for your needs something along the lines of:
$(function() {
if(document.getElementById('your_div_id_diamonds').innerHTML <=20 && document.getElementById('your_div_id_diamonds').innerHTML >=10) {
document.getElementById('elitecontent').className="gotelite";
}else {
document.getElementById('elitecontent').style.display="none";
}
}
});
should work.

jQuery keyup working incorrectly

I am trying to make an integer variable increment every time the Enter key is pressed. This variable is then used to output a value from an array.
$(document).keyup(function(e) {
if (e.keyCode == 13) {
console.log(++currSteps);
$('#output').text(outNum[currSteps])
if(outNum[currSteps] % 2 == 0){
$('body').css("background", "#4b84e5")
}
else if(outNum[currSteps] == 1){
$('body').css("background", "#9dd622")
}
else{
$('body').css("background", "#d16323")
}
}
});
The problem occurs when I actually press Enter. On the first press, it works properly, and increments the variable currSteps and displays the next value in the array. However, when I press Enter again, it reverts it back to the original value of currStep, as long as Enter is held down, it will display the original value.
Now, yes, this event is for keyup, therefore it makes sense that things will work oddly on keydown. However... if I open up the developer tools and click around in the console, and then return to my original window, the keyup code works perfectly. Why is this only working after the developer tools have been opened?
I have tried this on jQuery 1.11.1 and 1.10.2.
Edit: currSteps and outNum declarations.
$('#in').click(function(){
$('#output').empty();
$('#steps').empty();
var steps = 0
currSteps = 0
var inNum = parseInt($('#input').val());
var col = '#ffffff'
outNum = []
outNum.push(inNum)
...
I allowed to myself to write a little of your missing variables defition: JSFiddle
$(document).ready(function() {
var currSteps = 0;
var outNum = { 0: 0, 1: 1, 2: 2 };
$(document).keyup(function(e) {
if (e.keyCode == 13) {
console.log(++currSteps);
$('#output').val(outNum[currSteps] + ' ' + currSteps)
if(outNum[currSteps] % 2 == 0){
$('body').css("background", "#4b84e5")
}
else if(outNum[currSteps] == 1){
$('body').css("background", "#9dd622")
}
else{
$('body').css("background", "#d16323")
}
}
});
});
Is you problem still actual with upper demo?

Categories