ScrollTo: #div tag instead of top of page - smoothstate.js

I am trying to use the ScrollTo function in this little snippet of code so my page scrolls to an ID div tag instead of the top of page "0". Any help would be much appreciated!
Here is the code I'm using to scroll to the top of the page. All works fine just need to figure out how to add in a div location rather than it just going to the top.
I should also mention I am using smoothstate.js
Thanks so much for the help :)
$(function(){
'use strict';
var $body = $('html,body, #smoothState');
var options = {
prefetch: true,
cacheLength: 2,
blacklist: ".no-smoothstate a, .post-edit-link, a[href*='.jpg'], a[href*='.png'], a[href*='.jpeg'], a[href*='.pdf']",
onStart: {
duration: 0, // Duration of our animation
render: function ($container) {
$('.spinner').fadeIn(0);
// Add your CSS animation reversing class
$container.addClass('is-exiting');
$body.animate({
scrollTop: 0
});
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
$('.spinner').fadeOut(0);
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
}
},

Here is how I am doing it now. Seems to be working fine. Hope this helps out some others that are not so pro at jQuery like myself haha :)
$('html, body').animate({
scrollTop: $("#target-element").offset().top
}, 1000);

Related

Enable/Disable swiper dynamically (touch/mouse)

I have a page with a question and 4 answers, the swiper works great, I can go to the next question and back. What I want is to disable the swipe to the next question until an answer has been pressed. I successfully hide the 'next' arrow with a $scope variable and ng-show but the swipe with touch/mouse still works even after calling the initSwiper function with the new disabled options everytime I press an answer. Is this possible? This is the current initSwiper function that works really good.
$scope.initSwiper = function() {
var swiper = new Swiper('.swiper-container', {
// Navigation arrows
nextButton : '.swiper-button-next',
slideToClickedSlide : true,
onSlideChangeStart : function(swiper) {
$scope.index = swiper.activeIndex;
setExplanation($scope.index);
$scope.$apply();
$scope.test = $scope.tests[$scope.index];
swiper.lockSwipeToPrev();
}
});
}
My other init function that I call after an answer has been pressed it is just like this, I only add this swiper.lockSwipeToNext() to onSlideChangeStart: function.
You could try using the noSwipingClass option when you init the Swiper and use your $scope to conditionally apply a css class such as no-answer-yet to the Swiper slides. So something like:
$scope.initSwiper = function() {
var swiper = new Swiper('.swiper-container', {
...,
noSwipingClass: "no-answer-yet",
});
}

Proper way to create custom JS animations in angular 1.3+ with ng-animate

I want to use velocity.js in combination with ng-animate to create custom js-animations for my app. I've searched the web and found a lot of answers and tutorials which all refer to old versions of ng-animate, which apparently has changed the API a lot over time.
So right now, this is how my animation looks:
app.animation('.lb-fade', function () {
return {
addClass: function (element, className) {
element.velocity({
opacity: 1
},{
duration: 900,
easing: 'easeInSine'
});
}
};
});
I'm using it like this:
$animate.addClass(backdrop, 'lb-fade').then(console.log('promise resolved'));
This kind of works, but I have two problems:
The promise sometimes get's resolved to early (before the animation is finished). It looks like it is happening randomly.
How can I pass arguments to the animation? For example i want some of my lb-fade animations to use velocitys delay option. I could either create multiple animations (!DRY) or access the elements scope inside the animation (which seems really hacky to me). Is there a right way to do it?
Does it even make sense to use ng-animate alongside with velocity or should I just create my own functions to hold the animation code?
Maybe this is more like a workaround, but I wrote my own animator service now instead of using ngAnimate now. It uses angulars $q for implementing promises. Basically, this is just how ngAnimate does it, but somehow I think it doesn't know when velocity finished animating.
This is my service:
.service('animator', function animator($q) {
this.flyOutRight = function($element) {
return $q(function(resolve) {
$element.velocity({
//css properties to get animated
}, {
duration: 200,
complete: function () {
$element.remove();
resolve();
}
});
});
};
//some more animations
});
Usage:
animator.flyOutRight($oldImage).then(function(){
changeImageMutex = false;
});
It looks like you found a great workaround for your problem!
I think your original code didn't work since you didn't use the built-in done function. it's actually a wrapper for the default promise that ngAnimate returns at the end of an animation.
you used the function with the 2nd parameter className: function (element, className)
I used angular's ngAnimate as follows:
app.animation('.lb-fade', function () {
return {
addClass: function (element, doneFn) {
element.velocity({
opacity: 1
},{
duration: 900,
complete: doneFn
});
}
};
});
This works great for me.
It looks like the doneFn is still part of the api for ngAnimate.
Also, if you still want to use className (even though it looks like you didn't use it), you can use the function with it like so:
function(element, className, doneFn) {}

AngularJS Leaflet getMap() doesn't work

After adding Leaflet to my AngularJS app:
<leaflet id="map" defaults="defaults" center="center" bounds="bounds" controls="controls" event-broadcast="events"></leaflet>
And setting it up:
// Initialise the feature group to store editable layers
var drawnItems = new L.FeatureGroup();
// Initialise the draw control
var drawControl = new L.Control.Draw({
position: 'topright',
edit: {
featureGroup: drawnItems
}
});
// Configure Leaflet
angular.extend($scope, {
defaults: {
zoomControlPosition: 'topright',
minZoom: 3,
tileLayerOptions: {
detectRetina: true,
reuseTiles: true,
attribution: 'OpenStreetMaps'
}
},
center: {},
controls: {
custom: [drawControl]
},
events: {
map: {
enable: ['click']
}
}
});
Following this code it doesn't get evaluated (no error shown though):
leafletData.getMap().then(
function (map) {
alert('I have accessed the map.');
}
);
This should show me an alert straight away, although nothing happens.
If I delay this previous code, for example, running it in a function on a button click, it works!
Does anyone knows what could be a problem?
Seeing example, it should work: https://github.com/tombatossals/angular-leaflet-directive/blob/master/examples/control-draw-example.html
PARTLY SOLVED
Removing ID from leaflet HTML tag solved the problem. Must be a bug.
You are supposed to pass the id specified in the <leaflet> tag to getMap() function.
In your example, the id is map. You would pass it like this:
leafletData.getMap("map").then(
function (map) {
alert('I have accessed the map.');
}
);

Check if all Child-Components have been mounted

Is there any way to detect if the childs have been mounted? When i initialize the Isotope, all children components must be mounted for the initialize. With a timeout of 5ms it is working like expected, but im sure there is a better way.
componentDidMount: function() {
var container = this.refs.vinesOverview.getDOMNode();
setTimeout(function() {
var isotope = new Isotope(container, {
itemSelector: ".vine_item",
layoutMode: "masonry",
resizable: true,
gutter: 0,
isFitWidth: true
});
this.setState({ isotope: isotope });
}.bind(this), 5);
}
UPDATE
I have tried now this:
componentDidMount: function() {
var container = this.refs.vinesOverview.getDOMNode();
console.log(container.offsetHeight); // console output 0
setTimeout(function() {
console.log(container.offsetHeight); // console output 3150
}, 5);
},
So after 5ms it has calculated the height? Thats the reason why isotope isn't working. Is that a Bug or is that normal? Thanks!
React waits to mount all child components before calling componentDidMount on the parent. If you find a repro case where this isn't true, please file a bug.

How to center a mask in a Panel when rendering

I have a simple scenario where a panel needs a masked loading indicator over it while its loading the content. I have the mask working fine using the following code but the loading indicator appears at the top when calling it the first time. When calling it after the panel is shown, ie. on a button event, the mask appears correctly in the center of the panel. Any ideas?
var pnl = new Ext.Panel({
title: 'test',
width: 500,
height: 500,
renderTo: 'controls',
listeners: {
render: function(comp) {
comp.load();
}
},
load: function() {
this.el.mask('loading...', 'loadingMask');
}
});
It appears the mask is applied to the panel before the html has been rendered completely. A simple solution was to delay the mask shortly before applying it.
render: function(comp) {
setTimeout(function() { comp.loadPermissions(); }, 100);
}
Just call this.el.mask() from 'render' listener too. Also check this.rendered property before calling the mask in this.load method.

Resources