jQuery behavior on variable - javascript

I am customizing the jump example of markjs.
markjs_example
I have added some actions when I press the next button at the last instance of searched term, at this point it works.
if(currentIndex == 0 && jQuery(this).is($nextBtn)){
if(confirm("No more instances found! Go to the next page?")){
alert("NEXT PAGE");
}
}
Now I wanted to change the search behavior if I have reached the last marked word so I have added a variable i that I increment if I have reached the last marked word.
So i = 1 if nothing happened.
And i = 2 if I have reached the last word and pressed next, aka I am on the imaginary next page
To test all this I have added console log as you will see in the jsfiddle.
The problem is : it never prompt "page2" in the console, and i stays at 1, why?
jsfiddle_of_my_code

The code in if(i === 1) and else are evaluated only first time when page loads, and only the if condition is executed and registers the unmark method. Once i changes to 2 , the else condition for i===2 is never executed, therefore the second method $content.unmark is not registered or executed
You need to call unmark method once i changes to 2.
As in the code below,
jQuery(function() {
// the input field
$input = jQuery("input[type=\'search\']");
// clear button
var $clearBtn = jQuery("button[data-search=\'clear\']"),
// prev button
$prevBtn = jQuery("button[data-search=\'prev\']"),
// next button
$nextBtn = jQuery("button[data-search=\'next\']"),
// the context where to search
$content = jQuery(".content"),
// jQuery object to save <mark> elements
$results,
// the class that will be appended to the current
// focused element
currentClass = "current",
// top offset for the jump (the search bar)
offsetTop = 50,
// the current index of the focused element
currentIndex = 0,
//2 after last occurence reached
i = 1;
/**
* Jumps to the element matching the currentIndex
*/
function jumpTo() {
if ($results && $results.length) {
var position,
$current = $results.eq(currentIndex);
$results.removeClass(currentClass);
if ($current.length) {
$current.addClass(currentClass);
position = $current.offset().top - offsetTop - 100;
window.scrollTo(0, position);
}
}
}
/**
* Searches for the entered keyword in the
* specified context on input
*/
$input.on("input", function() {
searchVal = this.value;
$content.unmark({
done: function() {
$content.mark(searchVal, {
separateWordSearch: true,
done: function() {
$results = $content.find("mark");
currentIndex = 0;
console.log("page1");
console.log(i);
jumpTo();
}
});
}
});
});
function registerClear(){
$content.unmark({
done: function() {
$content.mark(searchVal, {
separateWordSearch: true,
done: function() {
$results = $content.find("mark");
currentIndex = 0;
console.log(searchVal);
console.log("page2");
jumpTo();
}
});
}
});
}
/**
* Clears the search
*/
$clearBtn.on("click", function() {
$content.unmark();
$input.val("").focus();
});
/**
* Next and previous search jump to
*/
$nextBtn.add($prevBtn).on("click", function() {
if ($results.length) {
currentIndex += jQuery(this).is($prevBtn) ? -1 : 1;
if (currentIndex < 0) {
currentIndex = $results.length - 1;
}
if (currentIndex > $results.length - 1) {
currentIndex = 0;
}
//if next pressed after last instance
if(currentIndex == 0 && jQuery(this).is($nextBtn)){
if(confirm("No more instances found! Go to the next page?")){
alert("NEXT PAGE");
i = 2;
registerClear();
}else{
//do nothing
}
}
jumpTo();
}
});
});

Related

JS random order showing divs delay issue

I got function within JS which is supposed to show random order divs on btn click.
However once the btn is clicked user got to wait for initial 10 seconds ( which is set by: setInterval(showQuotes, 10000) ) for divs to start showing in random order which is not ideal for me.
JS:
var todo = null;
var div_number;
var used_numbers;
function showrandomdivsevery10seconds() {
div_number = 1;
used_numbers = new Array();
if (todo == null) {
todo = setInterval(showQuotes, 10000);
$('#stop-showing-divs').css("display", "block");
}
}
function showQuotes() {
used_numbers.splice(0, used_numbers.length);
$('.container').hide();
for (var inc = 0; inc < div_number; inc++) {
var random = get_random_number();
$('.container:eq(' + random + ')').show();
}
$('.container').delay(9500).fadeOut(2000);
}
function get_random_number() {
var number = randomFromTo(0, 100);
if ($.inArray(number, used_numbers) != -1) {
return get_random_number();
} else {
used_numbers.push(number);
return number;
}
}
function randomFromTo(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
}
Question: How to alter the code so upon the btn click divs will start showing right away without initial waiting for 10 seconds? (take in mind I want to keep any further delay of 10 seconds in between of each div being shown)
Thank you.
Call it when you begin the interval
todo = setInterval((showQuotes(),showQuotes), 10000);

Starting timer when clicking first card of memory game

Ok I am trying to wrap up a project and the only thing holding me back is it that they call for the timer to start on clicking a match game. The timer starts when the HTML file loads which is not what the project wants and I have tried some methods but ends up freezing the game. I want the timer to be able to start when clicking a card.
var open = [];
var matched = 0;
var moveCounter = 0;
var numStars = 3;
var timer = {
seconds: 0,
minutes: 0,
clearTime: -1
};
//Start timer
var startTimer = function () {
if (timer.seconds === 59) {
timer.minutes++;
timer.seconds = 0;
} else {
timer.seconds++;
};
// Ensure that single digit seconds are preceded with a 0
var formattedSec = "0";
if (timer.seconds < 10) {
formattedSec += timer.seconds
} else {
formattedSec = String(timer.seconds);
}
var time = String(timer.minutes) + ":" + formattedSec;
$(".timer").text(time);
};
This is the code for clicking on a card. I have tried to include a startTimer code into this but doesn't work.
var onClick = function() {
if (isValid( $(this) )) {
if (open.length === 0) {
openCard( $(this) );
} else if (open.length === 1) {
openCard( $(this) );
moveCounter++;
updateMoveCounter();
if (checkMatch()) {
setTimeout(setMatch, 300);
} else {
setTimeout(resetOpen, 700);
}
}
}
};
And this class code I use for my HTML file
<span class="timer">0:00</span>
Try this: https://codepen.io/anon/pen/boWQbe
All you needed to do was remove resetTimer() call from the function that happens on page load and then just do a check in the onClick (of card) to see if the timer has started yet. timer.seconds == 0 && timer.minutes == 0.

setInterval increment index mystery

I am bangging my head against a wall, I cant figure out what is happening when I try increment my index value from outside my function.
So I starts off as 0, great! Each loop through i gets i +1 (this all seems great) ... but when I click #sliderNext you will see I dont add to the i value, yet it still increments the i value (why???) That means when I click prev I have to decrease the value by 2 instead of i-- (again, why?) ... am I being thick and not seeing something obvious?
Perhaps a better way to add prev + next (one that does not stop the setinterval completely)
$.when( loadImages() ).done(function(a1){
var i = 0;
var numberOfImgs = imgArr.length;
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]); //show with current i index
i++; //it should increment AFTER image has shown
if (i >= numberOfImgs || i < 0){ i = 0; }
}
sliderRotate();
intervalID = setInterval(sliderRotate, 3000);
//prev + next clicks
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
sliderRotate();
});
$('#sliderPrev').on( 'click' , function(){
clearTimeout(intervalID);
if ( i === 0 ){ i = imgArr.length -2; } //this only kind of works if I click twice on the first image
else{i = i - 2; }
sliderRotate();
});
});// end of when
Here is a snippet example:
$(document).ready(function(){
var imgArr = [
'<img src="http://www.freedigitalphotos.net/images/img/homepage/87357.jpg">',
'<img src="http://assets.barcroftmedia.com.s3-website-eu-west-1.amazonaws.com/assets/images/recent-images-11.jpg">',
'<img src="https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/pia20645_main.jpg?itok=dLn7SngD">',
'<img src="https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/pia18368-1041.jpg?itok=Fkc2j_kw">',
'<img src="http://www.irishtimes.com/polopoly_fs/1.2527148.1454955520!/image/image.jpg_gen/derivatives/landscape_685/image.jpg">',
'<img src="http://www.gettyimages.in/gi-resources/images/Homepage/Hero/US/Feb2016/video-481880130.jpg">'
];
var i = 0;
var numberOfImgs = imgArr.length;
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]);
i++; //should increment here, not before???
if (i >= numberOfImgs || i < 0){ i = 0; }
}
sliderRotate();
intervalID = setInterval(sliderRotate, 3000);
//prev + next clicks
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
sliderRotate();
});
$('#sliderPrev').on( 'click' , function(){
clearTimeout(intervalID);
if ( i === 0 ){ i = imgArr.length -2; } //kindah works, but still buggy
else{i = i - 2; }
sliderRotate();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sliderContainer">
<div id="sliderNext">Next</div><br><br><br>
<div id="sliderPrev">Prev</div>
<div id="autoSlider"></div>
</div>
Initial value of i is 0. sliderRotate function renders the first image (at index 0) and increments i by 1. In the next execution of this function the second image (at index 1) will be shown and i will have a value 2.
Now, you want to get back to the previous image (at index 0). But value of i is 2. You have to show image at index i - 2.
You are calling sliderRotate():
$('#sliderNext').on( 'click' , function(){
clearTimeout(intervalID);
//x = i + 1;
**sliderRotate();**
});
And that will increment it by 1:
function sliderRotate(passi){
$('#autoSlider').html(imgArr[i]);
i++; //should increment here, not before???
if (i >= numberOfImgs || i < 0){ i = 0; }
}
Same for "prev", you are adding 1 when you call sliderRotate(), that is why you need to subtract 2.
Here is a working example with your code: https://jsfiddle.net/owbL084z/2/

Autostart jQuery slider

I'm using a script that animates on click left or right to the next div. It currently works fine but I'm looking to add two features to it. I need it to repeat back to the first slide if it is clicked passed the last slide and go to the last slide if click back from the first slide. Also, I'm interested in getting this to autostart on page load.
I've tried wrapping the clicks in a function and setting a setTimeout but it didn't seem to work. The animation is currently using CSS.
Here's the current JS:
<script>
jQuery(document).ready(function() {
var boxes = jQuery(".box").get(),
current = 0;
jQuery('.right').click(function () {
if (current == (-boxes.length + 1)){
} else {
current--;
updateBoxes();
}
console.log(-boxes.length + 1);
console.log(current);
});
jQuery('.left').click(function () {
if (current === 0){
} else{
current++;
updateBoxes();
}
});
function updateBoxes() {
for (var i = current; i < (boxes.length + current); i++) {
boxes[i - current].style.left = (i * 100 + 50) + "%";
}
}
});
</script>
Let me know if I need a jsfiddle for a better representation. So far, I think the code is pretty straightforward to animate on click.
Thanks.
Try
jQuery(document).ready(function () {
var boxes = jQuery(".box").get(),
current = 0,
timer;
jQuery('.right').click(function () {
if (current == (-boxes.length + 1)) {
current = 0;
} else {
current--;
}
updateBoxes();
}).click(); //initialize the view
jQuery('.left').click(function () {
if (current === 0) {
current = -boxes.length + 1;
} else {
current++;
}
updateBoxes();
});
function updateBoxes() {
//custom implementation for testing
console.log('show', current)
$(boxes).hide().eq(-current).show();
autoPlay();
}
function autoPlay() {
clearTimeout(timer);
//auto play
timer = setTimeout(function () {
jQuery('.right').click();
}, 2500)
}
});
Demo: Fiddle
Here's an example based on my comment (mostly pseudocode):
$(function(){
var boxes = $('.box'),
current = 0,
timer;
// Handler responsible for animation, either from clicking or Interval
function animation(direction){
if (direction === 1) {
// Set animation properties to animate forward
} else {
// Set animation properties to animate backwards
}
if (current === 0 || current === boxes.length) {
// Adjust for first/last
}
// Handle animation here
}
// Sets/Clears interval
// Useful if you want to reset the timer when a user clicks forward/back (or "pause")
function setAutoSlider(set, duration) {
var dur = duration || 2000;
if (set === 1) {
timer = setInterval(function(){
animation(1);
}, dur);
} else {
clearInterval(timer)
}
}
// Bind click events on arrows
// We use jQuery's event binding to pass the data 0 or 1 to our handler
$('.right').on('click', 1, function(e){animation(e.data)});
$('.left').on('click', 0, function(e){animation(e.data)});
// Kick off animated slider
setAutoSlider(1, 2000);
Have fun! If you have any questions, feel free to ask!

Jquery slideshow starts with an image on the left of a row but I want it to start at the right end

I'm using this javascript and the slide show slides right to left with the images in this order and positon:
start postion > 1 | 2 | 3 | 4 | 5 | 6 etc etc
but I want to swap them so they run in this position
6 | 5 | 4 | 3 | 2 | 1 < start position
Kind of like reading a book back to front, but keeping it in the right order
I've been told I need to modify the lines labelled below: //MODIFY ME
I hope someone can help! Thank you
Here's my code
(function($) {
$.fn.slideshow = function(method) {
if ( this[0][method] ) {
return this[0][ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return this.each(function() {
var ANIMATION_DURATION = .6; // The duration to flick the content. In seconds.
var MOVE_THRESHOLD = 10; // Since touch points can move slightly when initiating a click this is the
// amount to move before allowing the element to dispatch a click event.
var itemWidth;
var horizontalGap;
var $this = $(this);
var collection;
var viewItems = [];
var touchStartTransformX; // The start transformX when the user taps.
var touchStartX; // The start x coord when the user taps.
var interval; // Interval used for measuring the drag speed.
var wasContentDragged; // Flag for whether or not the content was dragged. Takes into account MOVE_THRESHOLD.
var targetTransformX; // The target transform X when a user flicks the content.
var touchDragCoords = []; // Used to keep track of the touch coordinates when dragging to measure speed.
var touchstartTarget; // The element which triggered the touchstart.
var selectedIndex = 0; // The current visible page.
var viewPortWidth; // The width of the div that holds the horizontal content.
var isAnimating;
var pageChangedLeft;
// The x coord when the items are reset.
var resetX;
var delayTimeout;
init(method);
function init(options) {
collection = options.data;
renderer = options.renderer;
itemWidth = options.itemWidth;
horizontalGap = options.horizontalGap;
initLayout();
$this[0].addEventListener("touchstart", touchstartHandler);
$this[0].addEventListener("mousedown", touchstartHandler);
viewPortWidth = $this.width();
$this.on("webkitTransitionEnd", transitionEndHandler);
collection.on("add", addItem);
}
// MODIFY ME
function initLayout() {
// Layout five items. The one in the middle is always the selected one.
for (var i = 0; i < 5; i++) {
var viewItem;
if (i > 1 && collection.at(i - 2)) // Start at the one in the middle. Subtract 2 so data index starts at 0.
viewItem = new renderer({model: collection.at(i - 2)});
else
viewItem = new renderer();
viewItem.render().$el.appendTo($this);
viewItem.$el.css("left", itemWidth * i + horizontalGap * i);
viewItem.setState(i != 2 ? "off" : "on");
viewItems.push(viewItem);
}
// Center the first viewItem
resetX = itemWidth * 2 - ($this.width() - itemWidth - horizontalGap * 4) / 2;
setTransformX(-resetX);
}
function getCssLeft($el) {
var left = $el.css("left");
return Number(left.split("px")[0]);
}
// MODIFY ME
function transitionEndHandler() {
if (pageChangedLeft != undefined) {
var viewItem;
if (pageChangedLeft) {
// Move the first item to the end.
viewItem = viewItems.shift();
viewItems.push(viewItem);
viewItem.model = collection.at(selectedIndex + 2);
viewItem.$el.css("left", getCssLeft(viewItems[3].$el) + itemWidth + horizontalGap);
} else {
// Move the last item to the beginning.
viewItem = viewItems.pop();
viewItems.splice(0, 0, viewItem);
viewItem.model = collection.at(selectedIndex - 2);
viewItem.$el.css("left", getCssLeft(viewItems[1].$el) - itemWidth - horizontalGap);
}
viewItem.render();
// Reset the layout of the items.
for (var i = 0; i < 5; i++) {
var viewItem = viewItems[i];
viewItem.$el.css("left", itemWidth * i + horizontalGap * i);
viewItem.setState(i != 2 ? "off" : "on");
}
// Reset the transformX so we don't run into any rendering limits. Can't find a definitive answer for what the limits are.
$this.css("-webkit-transition", "none");
setTransformX(-resetX);
pageChangedLeft = undefined;
}
}
function touchstartHandler(e) {
clearInterval(interval);
wasContentDragged = false;
transitionEndHandler();
// Prevent the default so the window doesn't scroll and links don't open immediately.
e.preventDefault();
// Get a reference to the element which triggered the touchstart.
touchstartTarget = e.target;
// Check for device. If not then testing on desktop.
touchStartX = window.Touch ? e.touches[0].clientX : e.clientX;
// Get the current transformX before the transition is removed.
touchStartTransformX = getTransformX();
// Set the transformX before the animation is stopped otherwise the animation will go to the end coord
// instead of stopping at its current location which is where the drag should begin from.
setTransformX(touchStartTransformX);
// Remove the transition so the content doesn't tween to the spot being dragged. This also moves the animation to the end.
$this.css("-webkit-transition", "none");
// Create an interval to monitor how fast the user is dragging.
interval = setInterval(measureDragSpeed, 20);
document.addEventListener("touchmove", touchmoveHandler);
document.addEventListener("touchend", touchendHandler);
document.addEventListener("mousemove", touchmoveHandler);
document.addEventListener("mouseup", touchendHandler);
}
function measureDragSpeed() {
touchDragCoords.push(getTransformX());
}
function touchmoveHandler(e) {
var deltaX = (window.Touch ? e.touches[0].clientX : e.clientX) - touchStartX;
if (wasContentDragged || Math.abs(deltaX) > MOVE_THRESHOLD) { // Keep track of whether or not the user dragged.
wasContentDragged = true;
setTransformX(touchStartTransformX + deltaX);
}
}
function touchendHandler(e) {
document.removeEventListener("touchmove", touchmoveHandler);
document.removeEventListener("touchend", touchendHandler);
document.removeEventListener("mousemove", touchmoveHandler);
document.removeEventListener("mouseup", touchendHandler);
clearInterval(interval);
e.preventDefault();
if (wasContentDragged) { // User dragged more than MOVE_THRESHOLD so transition the content.
var previousX = getTransformX();
var bSwitchPages;
// Compare the last 5 coordinates
for (var i = touchDragCoords.length - 1; i > Math.max(touchDragCoords.length - 5, 0); i--) {
if (touchDragCoords[i] != previousX) {
bSwitchPages = true;
break;
}
}
// User dragged more than halfway across the screen.
if (!bSwitchPages && Math.abs(touchStartTransformX - getTransformX()) > (viewPortWidth / 2))
bSwitchPages = true;
if (bSwitchPages) {
if (previousX > touchStartTransformX) { // User dragged to the right. go to previous page.
if (selectedIndex > 0) { // Make sure user is not on the first page otherwise stay on the same page.
selectedIndex--;
tweenTo(touchStartTransformX + itemWidth + horizontalGap);
pageChangedLeft = false;
} else {
tweenTo(touchStartTransformX);
pageChangedLeft = undefined;
}
} else { // User dragged to the left. go to next page.
if (selectedIndex + 1 < collection.length) {// Make sure user is not on the last page otherwise stay on the same page.
selectedIndex++;
tweenTo(touchStartTransformX - itemWidth - horizontalGap);
pageChangedLeft = true;
} else {
tweenTo(touchStartTransformX);
pageChangedLeft = undefined;
}
}
} else {
tweenTo(touchStartTransformX);
pageChangedLeft = undefined;
}
} else { // User dragged less than MOVE_THRESHOLD trigger a click event.
var event = document.createEvent("MouseEvents");
event.initEvent("click", true, true);
touchstartTarget.dispatchEvent(event);
}
}
// Returns the x of the transform matrix.
function getTransformX() {
var transformArray = $this.css("-webkit-transform").split(","); // matrix(1, 0, 0, 1, 0, 0)
var transformElement = $.trim(transformArray[4]); // remove the leading whitespace.
return transformX = Number(transformElement); // Remove the ).
}
// Sets the x of the transform matrix.
function setTransformX(value) {
$this.css("-webkit-transform", "translateX("+ Math.round(value) + "px)");
}
function tweenTo(value) {
isAnimating = true;
targetTransformX = value;
// Set the style for the transition.
$this.css("-webkit-transition", "-webkit-transform " + ANIMATION_DURATION + "s");
// Need to set the timing function each time -webkit-transition is set.
// The transition is set to ease-out.
$this.css("-webkit-transition-timing-function", "cubic-bezier(0, 0, 0, 1)");
setTransformX(targetTransformX);
}
// MODIFY ME
function addItem(folio) {
clearTimeout(delayTimeout);
// Create a timeout in case multiple items are added in the same frame.
// When the timeout completes all of the view items will have their model
// updated. The renderer should check to make sure the model is different
// before making any changes.
delayTimeout = setTimeout(function(folio) {
var index = collection.models.indexOf(folio);
var dataIndex = index;
var firstIndex = selectedIndex - 2;
var dataIndex = firstIndex;
var viewItem;
for (var i = 0; i < viewItems.length; i++) {
viewItem = viewItems[i];
if (dataIndex >= 0 && dataIndex < collection.length) {
viewItem.model = collection.at(dataIndex);
viewItem.render();
}
viewItem.setState(i != 2 ? "off" : "on");
dataIndex += 1;
}
}, 200);
}
// Called when the data source has changed. Resets the view with the new data source.
this.setData = function(data) {
$this.empty();
viewItems = [];
collection = data;
selectedIndex = 0;
initLayout();
}
});
} else {
$.error( 'Method ' + method + ' does not exist on Slideshow' );
}
}
})(jQuery);
From what I can make out, you need to simply "flip" the loops that create the sides in the slideshow so that it makes the last slide where it was making the first. It seems to do this in two places.
Then, you will need to amend the code which adds a slide to make it add it before the other slides instead of after.
This sounds an awful lot like homework - it's always best to attempt an answer before asking on here. An example on a site like JSFiddle is also generally appreciated.

Categories