How to disable animations in protractor for angular js application - angularjs

Can anyone suggest me how to disable animations in angular js application while executing protractor tests. I have added below code in my protractor config file but that does not help me:
var disableNgAnimate = function() {
angular.module('disableNgAnimate', []).run(function($animate) {
$animate.enabled(false);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);

You can check out the angular's protractor configuration:
https://github.com/angular/angular.js/blob/master/protractor-shared-conf.js
You should add it under onPrepare block:
onPrepare: function() {
/* global angular: false, browser: false, jasmine: false */
// Disable animations so e2e tests run more quickly
var disableNgAnimate = function() {
angular.module('disableNgAnimate', []).run(['$animate', function($animate) {
$animate.enabled(false);
}]);
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);

I personally use the following code in the "onPrepare" function in my 'conf.js' file to disable both Angular/CSS animations:
...
onPrepare: function() {
var disableNgAnimate = function() {
angular
.module('disableNgAnimate', [])
.run(['$animate', function($animate) {
$animate.enabled(false);
}]);
};
var disableCssAnimate = function() {
angular
.module('disableCssAnimate', [])
.run(function() {
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
'-webkit-transition: none !important;' +
'-moz-transition: none !important' +
'-o-transition: none !important' +
'-ms-transition: none !important' +
'transition: none !important' +
'}';
document.getElementsByTagName('head')[0].appendChild(style);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);
browser.addMockModule('disableCssAnimate', disableCssAnimate);
}
...
Please note: I did not write the above code, I found it online while looking for ways to speed up my own tests.

Disabling CSS Animations / Transitions
In addition to disabling ngAnimation (ie, element(by.css('body')).allowAnimations(false);), you may need to disable some animation that has been applied through CSS.
I have found this sometimes contributes to some such animated elements, that may appear to Protractor to be 'clickable' (ie, EC.elementToBeClickable(btnUiBootstrapModalClose)), to not actually respond to .click(), etc.
In my particular case, I was suffering with a ui.bootstrap modal that transitioned in and out, and I wasn't always able to get its internal 'close' button reliably clicked.
I found that disabling css animations helped. I added a class to a stylesheet:
.notransition * {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
... and in protractor, I've got something like:
_self.disableCssAnimations = function() {
return browser.executeScript("document.body.className += ' notransition';");
};
There may be slicker ways of applying this concept, but I found that the above worked very well for me - in addition to stabilising the tests, they run quicker as they're not waiting for animations.

See this for an example: https://github.com/angular/protractor/blob/master/spec/basic/elements_spec.js#L123
it('should export an allowAnimations helper', function() {
browser.get('index.html#/animation');
var animationTop = element(by.id('animationTop'));
var toggledNode = element(by.id('toggledNode')); // animated toggle
// disable animation
animationTop.allowAnimations(false);
// it should toggle without animation now
element(by.id('checkbox')).click();
});

Related

using leaflet-popup-angular with ionic application

I am using this library for my ionic app. When I use leaflet-popup-angular with ionic,when I click the circle the popup doesn't work.and gives me this error Uncaught TypeError: Cannot read property 'get' of undefined.This errors sign this line inside the L.Popup.Angular.js library file.->>
var $rootScope = $injector.get('$rootScope'),
$compile = $injector.get('$compile'),
$controller = $injector.get('$controller');
.controller('MapCtrl', function ($scope) {
var map = L.map('map', { zoomControl: false });
var noControllerPopup = L.popup.angular({
template: `Hello world`,
}).setContent('But we can still use templates and $content.');
L.circle([51.508, -0.11], 500, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
}).addTo(map).bindPopup(noControllerPopup);
//my Tile...
});
can u please help me to solve this problem...
Update to version 1.0.1. Just released on bower and npm. The older versions assumed that you had your ng-app on the root html tag. This one looks for ng-app directly.

Why is angular-toastr not accepting the overriden postionClass.?

Plugin used: https://github.com/Foxandxss/angular-toastr
My intention is to create a toastr that spans the full with of the page on top and according to the documentation, positionClass: 'toast-top-full-width' will do the trick.
toastr.success('Hello world!', 'Toastr fun!', {
positionClass: 'toast-top-full-width'
});
A peek into the plugins css also validate the claim.
.toast-top-full-width {
top: 0;
right: 0;
width: 100%;
}
But somehow, the code doesn't work. Whats wrong with my code?
Plunkr: http://plnkr.co/edit/2O6hjk5vnMUWWULNK9hs?p=preview
You need to configure the toast in the angular config.
var app = angular.module('app', ['ngAnimate', 'toastr']);
app.config(function(toastrConfig) {
angular.extend(toastrConfig, {
positionClass: 'toast-top-full-width'
});
});
app.controller('toastr-demo', function($scope, toastr) {
toastr.success('Hello world!', 'Toastr fun!');
});
Plunker: http://plnkr.co/edit/pdstz2WkJqdi1Qw0R1pX?p=preview
Your problem is the toastContainer is not big enough, you should add a config like :
app.config(function(toastrConfig) {
angular.extend(toastrConfig, {
positionClass: 'toast-top-full-width'
});
});
This way, the container of all your toast will be full width, and then when you call a toast you can set his size to full-width.

Angular-ui FullCalendar open modal on eventClick feature in ionic framwork

I am using Ionic framework,I have successfully ported the fullCalender to my project,
I can able to call a funtion on eventClick, even it gives the alert of that event title perfectly.
But my main objective is to open the ionic modal instead of alert() with event title.
The code works till the alert comes, I am new to ionic need some idea how to acheive this.So far I have witten the code below
app.js Code:
$scope.calOptions = {
editable : true,
header : {
left: 'prev',
center: 'title,today',
right: 'next'
},
eventClick: function(calEvent, jsEvent, view){
var a=calEvent.description;
var b=calEvent.title;
alert('ALERT-1:' +a );
$scope.safeApply(function()
{
alert('ALERT-2:' + calEvent.description);
$scope.eventModal(a,b)
});
};
$scope.eventModal=function(a,b){
alert('ALERT-3:'+b);
$scope.eventModal.show();
}
$ionicModal.fromTemplateUrl('modal.html', function($ionicModal) {
$scope.eventModal = $ionicModal;
},{
scope: $scope,
// The animation we want to use for the modal entrance
animation: 'slide-in-up'
});
To be more clear the above code shows that the "eventClick:" works till "ALERT-3" ,however,on event click it calls the function "$scope.eventModal=function(a,b)" but after that at the next line at $scope.eventModal.show(); it says that "show is not a function", I want to open modal with variables passed to "$scope.eventModal=function(a,b)" function.
Need an idea to acheive open the modal with parameters passed to the "$scope.eventModal=function(a,b)".
Thanx in advance.
Try doing some simplier:
eventClick: function(calEvent, jsEvent, view){
$scope.a = calEvent.description;
$scope.b = calEvent.title;
$ionicModal.fromTemplateUrl('modal.html', {
scope: $scope
}).then(function (modal) {
$scope.modal = modal;
$scope.modal.show();
}).catch(function(err){
console.log(err);
});
};
And inside modal, you can bind {{::a}} and {{::b}} or whatever you want do with them.

Google I/O 2015 page like transition animations

recently I really like Google I/O 2015 event page, especially those transition animations between different states. I know they used Polymer for that, but I'm trying to recreate such delayed animations in Angular (1.4.1) and Angular-material and ui-router.
Basically what I want to achieve is this workflow:
before state change, animate leaving components of the app
leave some basic structure of the app (some basic holder containers)
make state change - resolve resources (REST API call)
transition to new state, with basic app structure (holders)
animate entering elements (with different delays)
This is not trivial task, and ng-animate is not very helpful, but I want to use is as much as possible. One drawback is, that leaving css classes are not added, before promises are resolved, the other it, that at one moment, both - old and new state view are present on the page.
I tried to create this directive:
(function() {
'use strict';
angular
.module('climbguide')
.directive('cgAnimateElement', cgAnimateElement);
/* #ngInject */
function cgAnimateElement($animate, $rootScope, $state) {
return {
restrict: 'A',
link: linkFunc
};
function linkFunc(scope, el) {
$animate.enter(el, el.parent());
var cleanUp = $rootScope.$on('$stateChangeStart',
function(event, toState, toParams) {
if ($rootScope.stateChangeBypass) {
$rootScope.stateChangeBypass = false;
return;
}
event.preventDefault();
var promise = $animate.leave(el);
promise.then(function() {
$rootScope.stateChangeBypass = true;
$state.go(toState.name, toParams);
});
});
scope.$on('$destroy', function() {
cleanUp();
});
}
}
})();
It basically does what I want, however for some reason it is only possible to use it one element - I assume because of the $rootScope.$on('$stateChangeStart') and later use of $state.go(toState.name, toParams);.
I also found two other solutions,
angular-ui-router-in-out, which uses CSS, but there is waiting for promises to be resolved before any animation happens (the loader animation would be necessary)
angular-gsapify-router, which uses javascript animations, and has the same problem as above one.
I'm still only learning angular, so I really don't know how to do this in a right way. Do you have any ideas? Thanks a lot.
P.S.: sorry for missing links to the libraries, but this is my first post to SO, so I can only post 2 links :)
Maybe it will help somebody, but I got it to work with probably dirty hack, but anyway it does, what I described in the original post.
I changed the directive so it can be re-used more times:
(function() {
'use strict';
angular
.module('climbguide')
.directive('cgAnimateElement', cgAnimateElement);
/* #ngInject */
function cgAnimateElement($animate, delayedRouterService) {
return {
restrict: 'A',
link: linkFunc
};
function linkFunc(scope, el) {
var stateChangeBypass = false;
$animate.enter(el, el.parent());
// Use scope instead of $rootScope, so there is no need to de-register listener
scope.$on('$stateChangeStart',
function(event, toState, toParams) {
if (stateChangeBypass) {
// Resuming transition to the next state broadcasts new $stateChangeStart
// event, so it necessary to bypass it
stateChangeBypass = false;
return;
}
delayedRouterService.holdStateChange(event);
var promise = $animate.leave(el);
promise.then(function() {
stateChangeBypass = true;
delayedRouterService.releaseStateChange(toState, toParams);
});
});
}
}
})();
I created service for handling state changes - preventing and resuming state changes in ui-router:
(function() {
'use strict';
angular
.module('climbguide')
.factory('delayedRouterService', delayedRouterService);
/* #ngInject */
function delayedRouterService($state) {
var _runningAnimations = 0;
/**
* Public methods
*
*/
var service = {
holdStateChange: holdStateChange,
releaseStateChange: releaseStateChange
};
return service;
//////////////
/**
* Prevent state change from the first animation
* Store the number of currently running animations
*
* #param event
*/
function holdStateChange(event) {
if (_runningAnimations === 0) {
event.preventDefault();
}
_runningAnimations++;
}
/**
* Remove animation from the stack after it is finished
* Resume state transition after last animation is finished
*
* #param toState
* #param toParams
*/
function releaseStateChange(toState, toParams) {
_runningAnimations--;
if (_runningAnimations === 0) {
$state.go(toState.name, toParams);
}
}
}
})();
So it's possible to use it in the HTML for the element which I want to animate
<div class="main" cg-animate-element>
...
</div>
And the final CSS:
.main {
&.ng-animate {
transition: opacity, transform;
transition-duration: 0.4s;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
&.ng-enter {
opacity: 0;
transform: translate3d(0, 100px, 0);
}
&.ng-enter-active {
opacity: 1;
transform: translate3d(0, 0, 0);
}
&.ng-leave {
opacity: 1;
transform: translate3d(0, 0, 0);
}
&.ng-leave-active {
opacity: 0;
transform: translate3d(0, 100px, 0);
}
}

How to rewrite this JQuery plugin into AngularJS

I have a code here and i want to make it usable for AngularJS. this's the original plugin PAPER COLLAPSE i want to use it in a AngularJS project so i'll be able to Do ng-repeat
here's the jQuery Plugin's code
(function() {
(function($) {
'use strict';
$.fn.paperCollapse = function(options) {
var settings;
settings = $.extend({}, $.fn.paperCollapse.defaults, options);
$(this).find('.collapse-card__heading').add(settings.closeHandler).click(function() {
if ($(this).closest('.collapse-card').hasClass('active')) {
settings.onHide.call(this);
$(this).closest('.collapse-card').removeClass('active');
$(this).closest('.collapse-card').find('.collapse-card__body').slideUp(settings.animationDuration, settings.onHideComplete);
} else {
settings.onShow.call(this);
$(this).closest('.collapse-card').addClass('active');
$(this).closest('.collapse-card').find('.collapse-card__body').slideDown(settings.animationDuration, settings.onShowComplete);
}
});
return this;
};
$.fn.paperCollapse.defaults = {
animationDuration: 400,
easing: 'swing',
closeHandler: '.collapse-card__close_handler',
onShow: function() {},
onHide: function() {},
onShowComplete: function() {},
onHideComplete: function() {}
};
})(jQuery);
}).call(this);
Thank you
It's quite easy, see this plunk. You'll probably want to tune the css abit.
There's no solid way to do a css only slideUp/slideDown, but if you don't mind including jquery you can always add a watch on card.$active and do the slide via jquery.

Resources