Cannot target Swiper slider variables as they are defined inside functions - javascript

I have 4 each functions which call a Swiper slider with the appropriate options. After those are appended to the correct div I then add the code which links them together, so one slider controls the other and vice versa.
I am getting the error "Uncaught ReferenceError: swiperV2 is not defined". I think this is because they are inside the each functions and this reference to them doesn't 'see' them.
Any ideas on how to fix this?
Thanks
$(".swiper-container-v").each(function(index, element) {
var $this = $(this);
$this.addClass("instance-" + index);
$this.find(".swiper-button-prev").addClass("btn-prev-" + index);
$this.find(".swiper-button-next").addClass("btn-next-" + index);
var swiperV = new Swiper(".swiper-container-v.instance-" + index, {
// your settings ...
pagination: '.swiper-pagination-v',
paginationClickable: true,
direction: 'vertical',
spaceBetween: 0,
mousewheelControl: false,
speed: 600,
nextButton: ".btn-next-" + index,
prevButton: ".btn-prev-" + index
});
});
$(".swiper-container-h").each(function(index, element) {
var $this = $(this);
$this.addClass("instance-" + index);
$this.find(".swiper-button-prev").addClass("btn-prev-" + index);
$this.find(".swiper-button-next").addClass("btn-next-" + index);
var swiperH = new Swiper(".swiper-container-h.instance-" + index, {
// your settings ...
pagination: '.swiper-pagination-h',
paginationClickable: true,
spaceBetween: 0,
parallax: true,
speed: 600,
nextButton: ".btn-next-" + index,
prevButton: ".btn-prev-" + index
});
});
$(".swiper-container-v2").each(function(index, element) {
var $this = $(this);
$this.addClass("instance-" + index);
$this.find(".swiper-button-prev").addClass("btn-prev-" + index);
$this.find(".swiper-button-next").addClass("btn-next-" + index);
var swiperV2 = new Swiper(".swiper-container-v2.instance-" + index, {
// your settings ...
paginationClickable: true,
direction: 'vertical',
spaceBetween: 0,
mousewheelControl: false,
speed: 600
});
});
$(".swiper-container-h2").each(function(index, element) {
var $this = $(this);
$this.addClass("instance-" + index);
$this.find(".swiper-button-prev").addClass("btn-prev-" + index);
$this.find(".swiper-button-next").addClass("btn-next-" + index);
var swiperH2 = new Swiper(".swiper-container-h2.instance-" + index, {
// your settings ...
paginationClickable: true,
spaceBetween: 0,
parallax: true,
speed: 600
});
});
swiperV2.params.control = swiperV;
swiperH2.params.control = swiperH;
swiperV.params.control = swiperV2;
swiperH.params.control = swiperH2;

Really.... this is just how scope works and is pretty much ubiquitous of all programming languages that are class/function based.
For you to be able to access variables that fall within the scope of a function, you must create a reference for it outside of that function in the scope that is expected to act upon it.
So in the case that you have something such as,
func() {
var myVar = ...
}
print(myVar)
This will not work as the global scope that exists outside of the functions scope has no concept of what myVar is.
So you'll need to first create a reference to that variable.
var myVar;
func() {
var myVar = ...
}
print(myVar)
Now since myVar was generated outside of the scope of the function, the function knows about myVar.
Alternatively you could return the value of myVar and do something like this.
func() {
return myVar = ...
}
var myFunc = func();
print(myFunc())
And you'll have essentially performed a function assignment (i.e., assigning that function to a variable) and that variable by proxy in this case is storing the return value of the function.

Related

How to make Swiper JS display faction pagination and progress bar at the same time?

How to make it so that the progress bar with the progress line and the numeric display of the active slide from the total number of slides are displayed simultaneously?
Since by default the simultaneous operation of the progress bar and pagination with a fraction is impossible, I added "type: 'progressbar'" in the "pagination" properties, and for the numeric display of slides I made an .image-slider__fraction block in which I placed all the elements.
Then I wrote java script code that I found on the Internet, but I get an error "Uncaught ReferenceError: myImageSLider is not defined". Why?
Site ilyin1ib.beget.tech
Code https://jsfiddle.net/qav8z7f3/
let mySliderAllSlides = document.querySelector('.image-slider__total');
let mySliderCurrentSlide = document.querySelector('.image-slider__current');
mySliderAllSlides.innerHTML = myImageSLider.slides.length;
myImageSLider.on('slideChange', function() {
let currentSlide = ++myImageSLider.realIndex;
mySliderCurrentSlide.innerHTML = currentSlide;
});
<div class="image-slider__fraction">
<div class="image-slider__current">1</div>
<div class="image-slider__sepparator">/</div>
<div class="image-slider__total">1</div>
</div>
use slideChange event. The script does not give the actual number of items because you used the loop inside the slider. That's why I found the value of the items before creating the slider script.
var totalSlide = $('.image-slider .swiper-slide').length;
const swiper = new Swiper('.image-slider', {
// Optional parameters
slidesPerView: 3,
spaceBetween: 30,
centeredSlides: true,
loop: true,
loopedSLides: 3,
simulateTouch: true,
grabCursor: true,
speed: 800,
pagination: {
el: '.swiper-pagination',
type: 'progressbar'
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
autoplay: {
delay: 1000,
}
});
//var count = $('.image-slider .image-slider__slide').length;
swiper.on('slideChange', function() {
var fragment = document.querySelector('.image-slider__current');
var current = swiper.realIndex + 1;
if (current > totalSlide)
current = 1;
var idx = current < 10 ? ("0" + current) : current;
var tdx = totalSlide < 10 ? ("0" + totalSlide) : totalSlide;
fragment.innerHTML = (idx + '/' + tdx);
});
demo in jsfiddle

Initializing javascript objects with variables that are functions within a for loop -- how to avoid overwriting?

I have this code:
for(i = 0; i < 1; i++){
$("body").append(questions[i]);
for(j = 0; j < prompts.length; j++){
var temp_id = "slider-" + j;
var temp_num_text_id = "slider-text-" + j;
var temptextdiv = $("<h5>50</h5>");
$("body").append(temptextdiv);
temptextdiv.attr('id', temp_num_text_id);
var tempdiv = $("<div></div>");
$("body").append(tempdiv);
tempdiv.attr('id', temp_id);
$("#" + temp_id).slider({
min: 0,
max: 100,
value: 50,
slide: function(event, ui){
$("#" + temp_num_text_id).html(ui.value);
}
});
}
}
The goal is to have one question with various prompts about the question, each being a ranking done on a jquery-ui slider. My trouble is trying to 'link' the text that displays the value of the slider with the slider itself. When I was testing this out with one slider it was as simple as the function within the declaration of the slider object shown above, but when this is done within a loop, all of the sliders only change the text value of the last slider. As I understand it from similar questions others have had, every iteration of the loop overwrites the previous declaration. How do I avoid this?
As I mentioned in the comment, all id attributes should be unique. This can be done by assigning a consecutive number to the ids.
For example: https://jsfiddle.net/Twisty/vLut8ysw/
JavaScript
var questions = [
"<div id='q1'>Question 1</div>",
"<div id='q2'>Question 2</div>",
"<div id='q3'>Question 3</div>",
"<div id='q4'>Question 4</div>",
"<div id='q5'>Question 5</div>",
];
var prompts = [
25,
50,
75,
];
var promptIds = 0;
$(function() {
$.each(questions, function(q, i) {
$(i).appendTo("body");
$.each(prompts, function(p, j) {
var temptextdiv = $("<h5>", {
id: "p-slider-text-" + promptIds
}).html(j).appendTo("body");
var tempdiv = $("<div></div>", {
id: "p-slider-" + promptIds
}).appendTo("body");
tempdiv.slider({
min: 0,
max: 100,
value: j,
slide: function(event, ui) {
temptextdiv.html(ui.value);
}
});
promptIds++;
});
});
});
This will create unique ids for each slider.

How to compare two different values of different functions or same function?

I have two variables index_1 and index_2 of different function and I have to compare that. Is that correct method or I can something else
Currently, I am not satisfied with this code for comparison because every time i get same value:
$(document).ready(function(){
var index_1 = '';
var index_2 = '';
$('#spin-now').click(function(){
$(".spin-box-1").jCarouselLite({
auto: 200,
speed: 200,
visible: 1,
vertical: true,
easing: "easeOutBounce",
afterEnd: function(a) {
var index_1 = $(a[0]).index();
store_index_1(index_1);
}
});
$(".spin-box-2").jCarouselLite({
auto: 225,
speed: 225,
visible: 1,
vertical: true,
easing: "easeOutBounce",
afterEnd: function(a) {
var index_2 = $(a[0]).index();
store_index_1(index_2);
}
});
});
function store_index_1(x){
data_index_1 = x;
data_index_2 = data_index_1 ;
if(data_index_2 == data_index_1){
//alert('same');
}
else{
alert('different');
}
console.log('outside'+''+data_index_1+''+data_index_2);
}
//console.log(data_index_1);
});
(I think this should be a comment, but I don't have enough reputation)
You defined 2 global variables, so if you're going to use them, then save your first index of .spin-box-1 in index_1 and .spin-box-2 in index_2, and then call a 'compare' function (your store_index_1).
$(document).ready(function(){
var index_1 = '';
var index_2 = '';
$('#spin-now').click(function(){
$(".spin-box-1").jCarouselLite({
auto: 200,
speed: 200,
visible: 1,
vertical: true,
easing: "easeOutBounce",
afterEnd: function(a) {
index_1 = $(a[0]).index(); //index_1 is your global
}
});
$(".spin-box-2").jCarouselLite({
auto: 225,
speed: 225,
visible: 1,
vertical: true,
easing: "easeOutBounce",
afterEnd: function(a) {
index_2 = $(a[0]).index(); //index_2 is your global
}
});
compare(); //index_1 and index2 should be set by this line.
});
function compare(){
if(index_1 == index_2){
alert('same');
}
else{
alert('different');
}
console.log('outside'+''+index_1+''+index_2);
}
//rest of your code
});
The thing with your store_index_1(x) function is that it will always be true because you are comparing 2 equal values:
data_index_2 = data_index_1 ;
if(data_index_2 == data_index_1)
That's kind of nonsense so i'm confused about what are you trying to do.
And again, sorry for the 'answer' 'cause I can't comment yet.

Replace JavaScript for loop with _.each() function

I am trying to replace a JavaScript For Loop with the underscore.js each() function.
for (var x = 0; x < count; x++) {
slider[x].setAttribute('id', arguments[x]);
sliderPagination[x].setAttribute('id', arguments[x]+'Pagination');
// Initialise swiper
var slider = new Slider('#'+arguments[x], {
pagination: '#'+arguments[x]+'Pagination',
loop:true,
grabCursor: true,
paginationClickable: true
})
}
I am new to using underscore so not quite sure the best way to do this. Do I need the index iteration when using the _.each() function for this?
UPDATE:
// Function to initialize multiple instances of slider plugin
function loadSliders(values) {
var sliders = document.getElementsByClassName("swiper-container"),
slidersPaginations = document.getElementsByClassName("swiper-pagination"),
count = Math.min(sliders.length, arguments.length),
i = 0;
_.each(sliders, function(sliders, index) {
var argumentsVariable = values[index];
sliders.setAttribute('id', argumentsVariable);
slidersPaginations[index].setAttribute('id', argumentsVariable+'Pagination');
// Initialise swiper
var slider = new Swiper('#'+argumentsVariable, {
pagination: '#'+argumentsVariable+'Pagination',
loop:true,
grabCursor: true,
paginationClickable: true
})
});
}
I'm assuming here that you have 3 arrays:
- sliders
- sliderPaginations
- arguments
Then, you can do it that way:
_.each(sliders, function(slider, index) {
var argumentsVariable = arguments[index];
slider.setAttribute('id', argumentsVariable);
sliderPaginations[index].setAttribute('id', argumentsVariable+'Pagination');
// Initialise swiper
var slider = new Slider('#'+argumentsVariable, {
pagination: '#'+argumentsVariable+'Pagination',
loop:true,
grabCursor: true,
paginationClickable: true
})
}
Note that you can use EcmaScript5 forEach method that is defined for each array:
sliders.forEach(function(slider, index) {
var argumentsVariable = arguments[index];
slider.setAttribute('id', argumentsVariable);
sliderPagination.setAttribute('id', argumentsVariable+'Pagination');
// Initialise swiper
var slider = new Slider('#'+argumentsVariable, {
pagination: '#'+argumentsVariable+'Pagination',
loop:true,
grabCursor: true,
paginationClickable: true
})
}

Javascript module pattern - what am I doing wrong?

A working version of this is here: http://est.pagodabox.com/client/svedka
I have the following function which I'm trying to convert into a module pattern, but when I try to use one of the function that I return at the bottom, for example:
est_project.closeContent($html);
I get an error that it's not a function. Is there something i'm doing wrong here?
Thanks!
var est_project = (function(){
// Setup functions
var flexDestroy,
cloneCurrent,
clonePosition,
switchSlide,
projectLayout,
contentHeight,
slidePos,
slideClick,
infoToggle,
closeContent;
// Destroy flexslider
flexDestroy = function($slider,$cleanSlider, $projBg) {
// Insert the clone of the un-initialized slide element, and remove the current flexslider
// Effectively "destroys" the current slider
var $curSlide = $slider.find('.flex-active-slide'),
// Get the zero based index of current slide
curSlideIndex = $curSlide.index() - 1,
curBg = $curSlide.find('img').attr('src'),
slideCount = $cleanSlider.data('count'),
i = 0,
$rearrange = $('');
// When you switch projects, the current slide should stay put
if(curSlideIndex !== 0 && slideCount > 1) {
// Cut from the current slide to the end, paste at the beginning
for(i = 0 ; i < slideCount; i += 1) {
if(curSlideIndex > i) {continue;}
$rearrange = $rearrange.add( $cleanSlider.find('li:eq(' + i + ')') );
}
$rearrange.remove();
$cleanSlider.find('li:first-child').before($rearrange)
$cleanSlider.css({'background-image' : 'url(' + curBg + ')'});
}
$slider.after($cleanSlider).remove();
clonePosition(slideheight);
};
return {
// Clone current
cloneCurrent: function($el) {
var $clean,
slideCount = $el.find('li').length;
$clean = $el.clone();
$clean.removeClass('project-current').find('div').removeClass('img-loading');
$clean.data('count',slideCount);
return $clean;
},
// Set the clone position, for when we add it to the DOM or resize the window
clonePosition: function(slideheight) {
var n = $cleanSlider.index(),
$myBg = $cleanSlider.find('div'),
myPosition = n * slideheight;
// Set the position of the inserted clone
$cleanSlider
.css({height: slideheight, top: myPosition, position : 'absolute'});
$myBg
.css({height: slideheight});
},
switchSlide: function($me, $slider) {
$('.project-current').removeClass('project-current');
$me.addClass('project-current');
// Get rid of current flexslider
flexDestroy($slider,$cleanSlider);
// Clone the unitialized slider so we can add it back in later when it gets destroyed
$cleanSlider = cloneCurrent($me);
$me.addClass('flexslider').flexslider({
animation: "slide",
animationSpeed: 500,
slideshow: false,
manualControls: '.dot-nav li a'
});
// After the flexslider initializes, slide the content
setTimeout(function(){
slidePos($me, $slidewrap, slideheight, $win);
},100);
},
// Custom "masonry" function, absolutely positions each project div according to the slide height
projectLayout: function(slideheight,$proj,$projBg) {
var n = 0;
$proj.each(function(){
var $me = $(this),
myPosition = n * slideheight;
// Set all the heights
$me
.css({top: myPosition, position : 'absolute'})
.add($projBg)
.css({height: slideheight});
n++;
});
},
// Set slide wrapper height to window height
contentHeight: function($win, $slidewrap) {
var winHeight = $win.height();
$slidewrap.css({height: winHeight});
},
// Set slide wrapper position to slide to the clicked slide, and set content position
slidePos: function($me, $slidewrap, slideheight, $win) {
var $contentText = $('.project-content .text'),
projNavHeight = Math.round( $win.height() * .1 ),
curIndex = $me.index(),
curTop = 0 - (curIndex * slideheight) + projNavHeight;
$slidewrap.css({transform: 'translate(0,' + curTop.toString() + 'px)'});
$('.corner-btn').add($contentText).css({'padding-top' : projNavHeight});
setTimeout(function(){
$slidewrap.removeClass('tr-none movin').addClass('tr-all');
$('.project').css({opacity: .4})
}, 100);
},
// Click a project, slide to it
slideClick: function($proj) {
$('.project').live('click',function(){
var $me = $(this),
myHref = $me.data('href'),
myTitle = $me.data('title'),
$slider = $('.flexslider'),
indexMy = $me.index(),
indexCur = $('.project-current').index(),
projDir;
$me.css({opacity: 1});
// Stop here if we click on the current project
if($me.hasClass('project-current')) {
return false;
}
History.pushState(null,myTitle,myHref);
});
},
// Hide and show content
infoToggle: function() {
// Open content
$('#corner-btn-info').on('click',function(){
$html.addClass('show-content');
if($('.project-content .text').height() <= $win.height()) {
$html.addClass('no-overflow');
}
$('.project-content-wrap').css({'z-index': 10});
});
// Close content
$('#corner-btn-close').live('click',function(){
closeContent($html);
});
},
closeContent: function($html) {
$html.removeClass('show-content');
setTimeout(function(){
$('.project-content-wrap').css({'z-index': -1});
$html.removeClass('no-overflow');
$('#classy').animate({scrollTop: 0})
},300);
}
};
});
The problem is that you're not executing the anonymous function, your code is the equivalent of:
var est_project = function() {};
You need to execute the function if you want it to return the functions defined in it.
Just replace the last line:
});
By:
}());
Or you can keep your code and call the closeContent function like this:
est_project().closeContent();
But I guess that's not what you want :-) You'd instantiate a new object everytime you call the est_project function.
At the start and end of your file just attach the object to window with the executed function and wrap whole function inside a self executing function. like this
(function(global) {
//your code goes here
global.est_project = est_project();
})(this)

Categories

Resources