Angular + jQuery, trigger scroll when src of image changes - javascript

I am trying to use jQuery to scroll to a particular thumbnail (inside a modal) when right/left arrows have been pressed (modal should pop up when user clicks on a image). I was able to make the scroll working when user clicks on a thumbnail but I could not trigger a click when variable current2 changes. Any help would be appreciated.
I am new in Angular.js so if there are other suggestions to improve the code, it would be appreciated.
jsbin link
<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">
<div class="row">
<div class="small-8 columns">
<div class="small-3 columns">
<div ng-repeat="obj in array">
<div ng-if="$index < 4">
<img ng-click="changeMainMedia($index, 'current1')" class="thumbnail" ng-src="{{obj.src}}" />
</div>
<div ng-if="$index == 4">
<div class="thumbnail" data-open="media-gallery">
<label class="text-right success label">{{array.length - 3}} +</label>
</div>
</div>
</div>
</div>
<div class="small-9 columns">
<img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
</div>
</div>
</div>
<div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
<div class="modal-body">
<div class="main-media">
<img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
<hr>
<div class="nested-media" scroll-thumbnail>
<img ng-click="changeMainMedia($index, 'current2')" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
</div>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">x</span>
</button>
</div>
</div>
<script>
var app = angular.module("mediaGallery", []);
app.controller("mediaGalleryCtrl", ['$scope', function(scope) {
var array = [{
src: "https://placeimg.com/640/480/any"
}, {
src: "https://placeimg.com/640/480/tech"
}, {
src: "https://placeimg.com/640/480/animals"
}, {
src: "https://placeimg.com/640/480/nature"
}, {
src: "https://placeimg.com/640/480/arch"
}, {
src: "https://placeimg.com/640/480/people"
}];
scope.array = array;
scope.current1 = 0
scope.current2 = 0;
scope.changeMainMedia = function(index, key) {
scope[key] = index;
}
scope.key = function($event) {
var previous = -1;
var current = scope.current2;
if ($event.keyCode == "39") {
previous = current;
current = (current + 1) % array.length;
} else if ($event.keyCode == "37") {
previous = current;
current = (current - 1) % array.length;
}
current = current < 0 ? (array.length + current) : current;
scope.current2 = current;
}
}]);
app.directive('scrollThumbnail', function() {
return {
link: function(scope, elem, attrs) {
elem.on("click", function(event) {
$(this).animate({
scrollLeft: $(event.target).position().left
}, "slow");
});
}
};
});
$(document).foundation()
</script>
</body>

This is a solution which does not need jQuery. I commented the changes that I have made to your code.
<!DOCTYPE HTML>
<html>
<head>
<title>index</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" />
<meta name="author">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/css/foundation.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.6/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/js/foundation.js"></script>
<style>
.media-gallery .media-gallery-thumbnail {
max-height: 5em;
display: inline-block
}
.media-gallery .media-gallery-main {
height: auto;
width: auto;
max-height: 20em;
}
.media-gallery .nested-media {
overflow-x: scroll;
white-space: nowrap;
}
.media-gallery .media-gallery-main {
max-width: 100%;
-moz-transition: all 0.3s;
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
.media-gallery .media-gallery-main:hover {
-moz-transform: scale(1.5);
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak {
display: none !important;
}
</style>
</head>
<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">
<div class="row">
<div class="small-8 columns">
<div class="small-3 columns">
<div ng-repeat="obj in array">
<div ng-if="$index < 4">
<img ng-click="changeMainMedia($index, 'current1', $event)" class="thumbnail" ng-src="{{obj.src}}" />
</div>
<div ng-if="$index == 4">
<div class="thumbnail" data-open="media-gallery">
<label class="text-right success label">{{array.length - 3}} +</label>
</div>
</div>
</div>
</div>
<div class="small-9 columns">
<img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
</div>
</div>
</div>
<div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
<div class="modal-body">
<div class="main-media">
<img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
<hr>
<div class="nested-media" scroll-thumbnail>
<img ng-click="changeMainMedia($index, 'current2', $event)" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
</div>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">x</span>
</button>
</div>
</div>
<script>
var app = angular.module("mediaGallery", []);
app.controller("mediaGalleryCtrl", ['$scope', function (scope) {
var array = [{
src : "https://placeimg.com/640/480/any"
}, {
src : "https://placeimg.com/640/480/tech"
}, {
src : "https://placeimg.com/640/480/animals"
}, {
src : "https://placeimg.com/640/480/nature"
}, {
src : "https://placeimg.com/640/480/arch"
}, {
src : "https://placeimg.com/640/480/people"
}
];
scope.array = array;
scope.current1 = 0
scope.current2 = 0;
scope.changeMainMedia = function (index, key, $event) {
scope[key] = index;
// Use scroll function to scroll to element after click
// $event parameter is added to retrieve the node value
scope.scroll($event.target);
}
// Animate scrolling
// Midified from: http://stackoverflow.com/a/8918062/529024
scope.scrollTo = function (element, to, duration) {
if (duration <= 0)
return;
var difference = to - element.scrollLeft;
var perTick = difference / duration * 10;
setTimeout(function () {
element.scrollLeft = element.scrollLeft + perTick;
if (element.scrollLeft === to)
return;
scope.scrollTo(element, to, duration - 10);
}, 10);
}
// calculate scroll position and starting scroll animation
scope.scroll = function (element) {
// Get center of parent
var left = element.offsetLeft;
var scroll = left - element.parentElement.scrollLeft;
// Start scroll
scope.scrollTo(element.parentElement, scroll, 300);
}
scope.key = function ($event) {
var previous = -1;
var current = scope.current2;
if ($event.keyCode == "39") {
previous = current;
current = (current + 1) % array.length;
} else if ($event.keyCode == "37") {
previous = current;
current = (current - 1) % array.length;
}
current = current < 0 ? (array.length + current) : current;
scope.current2 = current;
// Scroll to element
scope.scroll(scope.getElement());
}
// get the element that is matching current2 value
scope.getElement = function () {
var parent = scope.parentElement;
var children = parent.children();
return children.eq(scope.current2)[0];
}
// This function is used by directive scrollThumbnail to set the parent element
// and use it to get element sibilings
scope.setElement = function (element) {
scope.parentElement = element;
}
}
]);
app.directive('scrollThumbnail', function () {
return {
scope : true,
link : function (scope, elem, attrs) {
// set element to scope.parentElement.
scope.setElement(elem);
}
};
});
$(document).foundation()
</script>
</body>
</html>
And this a JSBin link: https://jsbin.com/ruzikilexe/1/edit?html,output

Related

Make splashscreen overlap elements

i am trying to make my splash screen overlap the website.
The splash screen gets pushed away by the elements that i want on the background.
here is my HTML
<!DOCTYPE html>
window.OneSignal = window.OneSignal || [];
OneSignal.push(function() {
OneSignal.init({
appId: "355bfb40-16e9-48aa-93c3-d9eb93775989",
});
});
Rabbadz
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,600&subset=latin-ext" rel="stylesheet">
<!-- CSS -->
<link href="assets/css/main.css" rel="stylesheet">
<!-- JS -->
<script src="assets/js/vendor/modernizr-2.8.3.min.js"></script>
<script src="assets/js/vendor/jquery-1.12.0.min.js"></script>
<script src="assets/js/plugins/animate-headline.js"></script>
<script src="assets/js/main.js"></script>
</head>
<body>
<audio id="myAudio">
<source src="assets/sound.mp3" type="audio/mpeg">
</audio>
<!--logo-->
<img src="assets/images/logo.png" class="logo">
<!-- Options headline effects: .rotate | .slide | .zoom | .push | .clip -->
<div class="hero-section hero-section--color clearfix zoom">
<!--we are rabbadz-->
<div class="anitext">
<div class="title-01 title-01--11 text-center">
<h2 class="title__heading">
<div class="hero-section__words text-center">
<div class="title__effect is-visible">WE ARE RABBITS</div>
<div class="title__effect">WE ARE BADASS</div>
<div class="title__effect">WE ARE RABBADZ</div>
</div>
</h2>
<div class="title__description">Coming soon to the metaverse.</div>
<!-- Options btn color: .btn-success | .btn-info | .btn-warning | .btn-danger | .btn-primary -->
<div class="title__action">MINT</div>
</div>
</div>
</div>
</div>
</div>
<!--Particles-->
<div
id="particles-js"></div>
<script src="assets/js/particles.js"></script>
<script src="assets/js/app.js"></script>
<!-- splashscreen-->
<div class="scene content-hidden scene">
<div class="scene">
<div class="moon"></div>
</div>
<script type="text/javascript">
function stars(){
let count = 500;
let scene = document.querySelector('.scene');
let i = 0;
while(i < count){
let star = document.createElement("i");
let x = Math.floor(Math.random() * window.innerWidth);
let y = Math.floor(Math.random() * window.innerHeight);
let duration = Math.random() * 10;
let size = Math.random() * 2;
star.style.left = x+'px';
star.style.top = y+'px';
star.style.width = 1+size+'px';
star.style.height = 1+size+'px';
star.style.animationDuration = 5+duration+'s';
star.style.animationDelay = duration+'s';
scene.appendChild(star);
i++
}
}
stars();
</script>
<!--Rabbadverse button-->
$(function() {
var scene = $('.scene'),
enterButton = scene.find('.knop');
setTimeout(function() {
scene.removeClass('content-hidden');
}, 500);
enterButton.on('click', function(e) {
e.preventDefault();
scene.addClass('content-hidden').fadeOut();
});
var anitext = $('.forest'),
enterButton = scene.find('.knop');
setTimeout(function() {
forest.removeClass('content-hidden');
}, 500);
enterButton.on('click', function(e) {
e.preventDefault();
forest.addClass('content-hidden').fadeOut();
});
});
</script>
var x = document.getElementById("myAudio");
function playAudio() {
x.play();
}
function pauseAudio() {
x.pause();
}
</body>
If I understand it right, you want your "scene" div above the black background div.
You could achieve this by this simple css:
.scene {
position: fixed; /* make it relative to the viewport */
inset: 0; /* make the div close to the edge of the relative element, here the viewport, so it takes the full screen */
}

call clearInterval on mouseleave

I'm trying to create an image slideshow with setInterval which starts playing when the mouse is over .project-img and pauses when the mouse leaves .project-img. The problem i'm having is calling clear interval on to pause the slideshow when the mouse leaves, I'm currently receiving the error:
Uncaught ReferenceError: cycle is not defined
Where am I going wrong?
var Image = {
init: function() {
Image.setupImages();
Image.bindEvents();
},
bindEvents: function() {
$('.project-img').hover(function() {
var hovered = $(this);
var thumbnailIndex = 0
var thumbnailArray = hovered.children()
console.log(thumbnailArray);
var cycle = setInterval(function(){
thumbnailIndex++
if (thumbnailIndex === thumbnailArray.length) {
thumbnailIndex = 0;
thumbnailArray.removeClass('active');
thumbnailArray.eq(0).addClass('active');
} else {
var $visible = thumbnailArray.eq(thumbnailIndex);
thumbnailArray.removeClass('active');
$visible.addClass('active');
}
}, 700);
}, function() {
clearInterval(cycle);
});
},
setupImages: function() {
var projectImage = $('.project-img');
projectImage.each(function(project) {
$(this).find('.project-thumbnail:eq(0)').addClass('active');
});
}
}
$(document).ready(function() {
Image.init();
});
.project-thumbnail {
visibility: hidden;
display: none;
}
.active {
visibility: visible;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
</div>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
</div>
This is a scope issue, you have defined cycle within a function, so it can't leave. Put var cycle above var Image and your problems will be solved! Alternatively if you wanted to keep it scoped inside the Image var, you can replace cycle with Image.cycle and that will also work.
The variable cycle is in a different scope. Instead of using hover use each, declaring the cycle variable in an outer scope of hover like so:
var Image = {
init: function() {
Image.setupImages();
Image.bindEvents();
},
bindEvents: function() {
$('.project-img').each(function() {
var hovered = $(this);
var cycle;
hovered.hover(function() {
var thumbnailIndex = 0;
var thumbnailArray = hovered.children();
cycle = setInterval(function() {
thumbnailIndex++
if (thumbnailIndex === thumbnailArray.length) {
thumbnailIndex = 0;
thumbnailArray.removeClass('active');
thumbnailArray.eq(0).addClass('active');
} else {
var $visible = thumbnailArray.eq(thumbnailIndex);
thumbnailArray.removeClass('active');
$visible.addClass('active');
}
}, 700);
}, function() {
clearInterval(cycle);
});
});
},
setupImages: function() {
var projectImage = $('.project-img');
projectImage.each(function(project) {
$(this).find('.project-thumbnail:eq(0)').addClass('active');
});
}
}
$(document).ready(function() {
Image.init();
});
.project-thumbnail {
visibility: hidden;
display: none;
}
.active {
visibility: visible;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
</div>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
</div>

JS Fiddle. Saved code but not working like JSFiddle example

I have found a very nice example on JSFiddle
http://jsfiddle.net/zra6fvtt/2/
When I try to save that, it does not work in my file which I created with the JSFiddle information. Here is my code:
/* =========================================================
* imageimageviewer.js
* =========================================================
* Controls the interaction with the product images on the PDP and collection PDP. A large image is presented with a
* series of thumbnails. If there are more than X (configurable) thumbnails, a scroller allows the user to see the
* others. Clicking on a thumbnail will change the large image. If the user scolls past the active thumbnail, the first thumbnail in the visible set will become active and the main image will update. If the user navigates by swiping the large image, the thumbnail strip will update to reflect the user's selection.
* ========================================================= */
(function(global, $, namespace) {
"use strict";
var Imageviewer = function Imageviewer(element, options) {
this.init('imageviewer', element, options);
},
loggingDebug = true;
//PUBLIC
Imageviewer.prototype = {
constructor: Imageviewer,
init: function init(type, element, options) {
if (loggingDebug) {
console.debug('init imageviewer with options:');
console.debug(Array.prototype.slice.call(arguments));
}
var self = this;
this.options = $.extend({}, $.fn[type].defaults, options);
this.$element = $(element);
this.$navigation = this.$element.find(this.options.thumbnail_container_class);
this.$mainView = this.$element.find(this.options.large_container_class);
this.totalSlides = this.$navigation.find(this.options.thumbnail_class).length;
this.slidesToShow = self.options.slider_min;
this.$navigation.find(this.options.thumbnail_class).first().addClass('active');
this.$mainView.slick({
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
fade: true,
infinite: false,
onAfterChange: function() {
var index = self.$mainView.slickCurrentSlide();
// catch when user has dragged the main image and update the nav to match
if (self.getActiveSlide() != index) {
self.setActiveSlide(index);
if (!self.isSlideVisible(index, self.$navigation.slickCurrentSlide())) {
self.$navigation.slickGoTo(Math.floor(index / self.slidesToShow) * self.slidesToShow);
}
}
}
});
this.$navigation.slick({
slidesToShow: self.options.slider_min,
slidesToScroll: self.options.slider_min,
dots: false,
infinite: false,
onAfterChange: function() {
var index = self.$mainView.slickCurrentSlide();
if (!self.isSlideVisible(index, self.$navigation.slickCurrentSlide())) {
self.$mainView.slickGoTo(self.getFirstVisibleSlide(self.$navigation.slickCurrentSlide()));
self.setActiveSlide(self.getFirstVisibleSlide(self.$navigation.slickCurrentSlide()));
}
}
});
this.$navigation.find(this.options.thumbnail_class).click(function(e) {
var index = parseInt(this.getAttribute('index'));
self.setActiveSlide(index);
self.$mainView.slickGoTo(index);
});
},
getFirstVisibleSlide: function(currentSlide) {
var firstSlide = currentSlide;
if (currentSlide + this.slidesToShow >= this.totalSlides) {
firstSlide = this.totalSlides - this.slidesToShow;
}
return firstSlide;
},
isSlideVisible: function(slideIndex, currentSlide) {
var isVisible = false;
if (currentSlide + this.slidesToShow > this.totalSlides) {
isVisible = (slideIndex >= this.totalSlides - this.slidesToShow) && (slideIndex <= this.totalSlides - 1);
} else {
isVisible = (slideIndex >= currentSlide) && (slideIndex <= currentSlide + this.slidesToShow - 1);
}
return isVisible;
},
getActiveSlide: function() {
var slideIndex = this.$navigation.find('.active').index() || 0;
return slideIndex;
},
setActiveSlide: function(index) {
this.$navigation.find(this.options.thumbnail_class).removeClass('active').end()
.find("[index='" + index + "']").addClass('active')
}
};
$.fn.imageviewer = function imageviewer(option) {
var el = this,
options = $.extend({}, $.fn.imageviewer.defaults, typeof option === 'object' && option);
return el.each(function() {
var data = $.data(this, 'imageviewer');
if (!data) {
$.data(this, 'imageviewer', (data = new Imageviewer(this, options)));
} else {
if (typeof option === 'object') {
$.extend(data.options, option);
}
}
});
};
$.fn.imageviewer.defaults = {
large_container_class: ".viewer-main",
thumbnail_container_class: ".viewer-thumbnails",
thumbnail_class: ".viewer-thumb",
slider_min: 5
};
$.fn.imageviewer.Constructor = Imageviewer;
$(function() {
$('[data-imageviewer]').imageviewer();
});
}(this, window.jQuery, "CLIENT"));
.viewer-thumbnails-container {
margin: 0 40px;
}
.viewer-thumb {
border: solid 2px transparent;
margin: 2px;
}
.viewer-thumb.active {
border: solid 2px black;
}
img {
max-width: 100%;
}
.slick-prev:before,
.slick-next:before {
color: black;
}
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.3.15/slick.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.3.15/slick.css">
<div class="product-image-viewer" data-imageviewer>
<div class="viewer-main">
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+1" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+2" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+3" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+4" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+5" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+6" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+7" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+8" />
</div>
</div>
<div class="viewer-thumbnails-container">
<div class="viewer-thumbnails">
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+1" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+2" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+3" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+4" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+5" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+6" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+7" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+8" />
</div>
</div>
</div>
</div>
Add this tag <script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
jQuery is imported in the fiddle

Start counting after scroll on specific element

I create a website and add a counter to my codes.
$(function() {
function count($this){
var current = parseInt($this.html(), 10);
$this.html(++current);
if(current !== $this.data('count')){
setTimeout(function(){count($this)}, 50);
}
}
$(".c-section4").each(function() {
$(this).data('count', parseInt($(this).html(), 10));
$(this).html('0');
count($(this));
});
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<div class="section4">
<div class="section4-bg"></div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
</div>
Now i have a problem, i want to counter start when i scroll to this element
Demo
Sorry for my bad english
You can handle the window scroll event and use the function given here by Scott Dowding to determine if the element has been scrolled into view. An isCounting flag can be set on each element to prevent counting several times simultaneously.
In the following code snippet, the counting is performed only while the element is visible.
$(function () {
function isScrolledIntoView($elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function count($this) {
var current = parseInt($this.html(), 10);
if (isScrolledIntoView($this) && !$this.data("isCounting") && current < $this.data('count')) {
$this.html(++current);
$this.data("isCounting", true);
setTimeout(function () {
$this.data("isCounting", false);
count($this);
}, 50);
}
}
$(".c-section4").each(function () {
$(this).data('count', parseInt($(this).html(), 10));
$(this).html('0');
$(this).data("isCounting", false);
});
function startCount() {
$(".c-section4").each(function () {
count($(this));
});
};
$(window).scroll(function () {
startCount();
});
startCount();
});
.tallDiv
{
height: 800px;
background-color: silver;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<div class="section4">
<div class="section4-bg"></div>
<div class="tallDiv">Scroll down to test</div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
<div class="counter-section">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
<div class="tallDiv"></div>
</div>
You need to give the target element and id, then get its postition from top var pos = document.getElementById('targetId').scrollHeight - element.clientHeight; and compare it to the scrolled height window.pageYOffset.
If widow offset is greater than the pos, you can start the counter. You should hook the comparison to the window.onscroll event.
Also you should memorize in a variable if you started the counter for an element already to avoid starting it twice.
Get the scroll Height and compare with the height of the start div(count start div) put a condition
$(function() {
var pos = document.getElementById('targetId').scrollHeight;
console.log(pos);
if(pos>="75"){
function count($this){
var current = parseInt($this.html(), 10);
$this.html(++current);
if(current !== $this.data('count')){
setTimeout(function(){count($this)}, 50);
}
}
$(".c-section4").each(function() {
$(this).data('count', parseInt($(this).html(), 10));
$(this).html('0');
count($(this));
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="counter-section" id="targetId">
<span class="c-section4">152 </span>
<h3> کارکنان ما </h3>
</div>
Live Link
You can use this Plugin for it. Source LINK
<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0'
data-max='82' data-delay='19' data-increment="2">0</span>
NB: data-max='**'give your max-number and data-delay='**' select a time for countdown running and select increment data-increment="**" .
/**
* jQuery scroroller Plugin 1.0
*
* http://www.tinywall.net/
*
* Developers: Arun David, Boobalan
* Copyright (c) 2014
*/
(function($){
$(window).on("load",function(){
$(document).scrollzipInit();
$(document).rollerInit();
});
$(window).on("load scroll resize", function(){
$('.numscroller').scrollzip({
showFunction : function() {
numberRoller($(this).attr('data-slno'));
},
wholeVisible : false,
});
});
$.fn.scrollzipInit=function(){
$('body').prepend("<div style='position:fixed;top:0px;left:0px;width:0;height:0;' id='scrollzipPoint'></div>" );
};
$.fn.rollerInit=function(){
var i=0;
$('.numscroller').each(function() {
i++;
$(this).attr('data-slno',i);
$(this).addClass("roller-title-number-"+i);
});
};
$.fn.scrollzip = function(options){
var settings = $.extend({
showFunction : null,
hideFunction : null,
showShift : 0,
wholeVisible : false,
hideShift : 0,
}, options);
return this.each(function(i,obj){
$(this).addClass('scrollzip');
if ( $.isFunction( settings.showFunction ) ){
if(
!$(this).hasClass('isShown')&&
($(window).outerHeight()+$('#scrollzipPoint').offset().top-settings.showShift)>($(this).offset().top+((settings.wholeVisible)?$(this).outerHeight():0))&&
($('#scrollzipPoint').offset().top+((settings.wholeVisible)?$(this).outerHeight():0))<($(this).outerHeight()+$(this).offset().top-settings.showShift)
){
$(this).addClass('isShown');
settings.showFunction.call( this );
}
}
if ( $.isFunction( settings.hideFunction ) ){
if(
$(this).hasClass('isShown')&&
(($(window).outerHeight()+$('#scrollzipPoint').offset().top-settings.hideShift)<($(this).offset().top+((settings.wholeVisible)?$(this).outerHeight():0))||
($('#scrollzipPoint').offset().top+((settings.wholeVisible)?$(this).outerHeight():0))>($(this).outerHeight()+$(this).offset().top-settings.hideShift))
){
$(this).removeClass('isShown');
settings.hideFunction.call( this );
}
}
return this;
});
};
function numberRoller(slno){
var min=$('.roller-title-number-'+slno).attr('data-min');
var max=$('.roller-title-number-'+slno).attr('data-max');
var timediff=$('.roller-title-number-'+slno).attr('data-delay');
var increment=$('.roller-title-number-'+slno).attr('data-increment');
var numdiff=max-min;
var timeout=(timediff*1000)/numdiff;
//if(numinc<10){
//increment=Math.floor((timediff*1000)/10);
//}//alert(increment);
numberRoll(slno,min,max,increment,timeout);
}
function numberRoll(slno,min,max,increment,timeout){//alert(slno+"="+min+"="+max+"="+increment+"="+timeout);
if(min<=max){
$('.roller-title-number-'+slno).html(min);
min=parseInt(min)+parseInt(increment);
setTimeout(function(){numberRoll(eval(slno),eval(min),eval(max),eval(increment),eval(timeout))},timeout);
}else{
$('.roller-title-number-'+slno).html(max);
}
}
})(jQuery);
.nm {
height: 400px;
background: #f5f5f5;
display: block;
}
.nm_1 {
background-color: #632525;
}
.nm_2 {
background-color: grad;
}
.nm_3 {
background-color: gray;
}
.nm_4 {
background-color: green;
}
.nm_5 {
background-color: georgian;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="nm nm_1">
</section>
<section class="nm nm_2">
</section>
<section class="nm nm_3">
</section>
<section class="nm nm_4">
<div>
<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='192' data-delay='19' data-increment="2">0</span>
<h3> کارکنان ما </h3>
</div>
<div>
<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='282' data-delay='19' data-increment="2">0</span>
<h3> کارکنان ما </h3>
</div>
<div>
<span class='numscroller numscroller-big-bottom' data-slno='1' data-min='0' data-max='82' data-delay='19' data-increment="2">0</span>
<h3> کارکنان ما </h3>
</div>
</section>
<section class="nm nm_4">
</section>
<section class="nm nm_5">
</section>
Here's my solution which supports floats and a configurable animation duration. It will only animate the count one time - as soon the element appears in the viewport of the specified container.
const initAnimatedCounts = () => {
const ease = (n) => {
// https://github.com/component/ease/blob/master/index.js
return --n * n * n + 1;
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Once this element is in view and starts animating, remove the observer,
// because it should only animate once per page load.
observer.unobserve(entry.target);
const countToString = entry.target.getAttribute('data-countTo');
const countTo = parseFloat(countToString);
const duration = parseFloat(entry.target.getAttribute('data-animateDuration'));
const countToParts = countToString.split('.');
const precision = countToParts.length === 2 ? countToParts[1].length : 0;
const startTime = performance.now();
const step = (currentTime) => {
const progress = Math.min(ease((currentTime - startTime) / duration), 1);
entry.target.textContent = (progress * countTo).toFixed(precision);
if (progress < 1) {
animationFrame = window.requestAnimationFrame(step);
} else {
window.cancelAnimationFrame(animationFrame);
}
};
let animationFrame = window.requestAnimationFrame(step);
}
});
});
document.querySelectorAll('[data-animateDuration]').forEach((target) => {
target.setAttribute('data-countTo', target.textContent);
target.textContent = '0';
observer.observe(target);
});
};
initAnimatedCounts();
div {
font-size: 30px;
text-align: center;
padding: 30px 0;
}
div > span {
color: #003d82;
}
div.scrollpad {
height: 100vh;
background-color: #eee;
}
<div>
<span>$<span data-animateDuration="1000">987.45</span></span> was spent on
about <span><span data-animateDuration="1000">5.8</span>M</span> things.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
There are <span><span data-animateDuration="1000">878</span>K</span> people involved.
<br/>
And <span><span data-animateDuration="1000">54</span></span> cakes.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
Additionally, <span>$<span data-animateDuration="3000">300</span>B</span> went to waste.
<br/>
Because <span>$<span data-animateDuration="2000">54</span></span> was spent on each cake.
</div>
<div class="scrollpad">keep scrolling</div>
<div>
Lastly, <span><span data-animateDuration="4000">3.5334583</span>T</span> ants said hello.
<br/>
But <span><span data-animateDuration="2000">4</span></span> of them said goodbye.
</div>

Angular js make slider with infinite effect

I created a simple photo slider but i does not how to make this infinite.
How can i make this effect with the angular way, please help.
I does not want to use jquery, but if it is the only way so whatever.
var app = angular.module('stack', []);
app.controller('MainCtrl', function($scope) {
$scope.images = ["http://lorempixel.com/600/200/sports/", "http://lorempixel.com/600/200/city/",
"http://lorempixel.com/600/200/nature/"
];
$scope.index = 0;
var IMG_WIDTH = -600;
$scope.next = function() {
++$scope.index;
if ($scope.images.length <= $scope.index) {
$scope.index = 0;
}
var pos = ($scope.index > 0) ? $scope.index * IMG_WIDTH : 0;
$scope.listPosition = {
transform: "translateX(" + pos + "px)"
};
}
$scope.prev = function() {
--$scope.index;
if ($scope.index < 0) {
$scope.index = $scope.images.length - 1;
}
var pos = ($scope.index > 0) ? $scope.index * IMG_WIDTH : 0;
$scope.listPosition = {
transform: "translateX(" + pos + "px)"
};
}
});
.mt {
margin-top: 2em;
}
.outer {
max-width: 600px;
overflow: hidden;
}
.slider {
width: 90000px;
position: relative;
transition: all 1s;
}
.slider div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link data-require="bootstrap#3.3.2" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<body ng-app="stack" ng-controller="MainCtrl">
<div class="container-fluid">
<div class="row mt">
<div class="col-sm-6 col-sm-push-3">
<div class="outer clearfix">
<div class="slider clearfix" ng-style="listPosition">
<div ng-repeat="image in images track by $index">
<img ng-src="{{image}}" />
</div>
</div>
</div>
</div>
</div>
</div>
<a class="btn btn-default" ng-click="next()">Next</a>
<a class="btn btn-default" ng-click="prev()">Prev</a>
<div></div>
</body>
Easiest way would be to shuffle $scope.images array.
Once transition has been done, disable them, either by creating something like .no-transition class and adding it to the slider or by any other way you can imagine
$scope.images.push($scope.images.shift()) should put first item to last position, $scope.images.unshift($scope.images.pop()) should reverse it.
After that, you'll probably have to re-adjust transform value and re-apply transitions
Hope that helps.

Categories