I finally got PJAX all setup and working perfect on my Foundation 5 site and its time to add my page transitions. For some reason no matter what I try the page loads and then the transition happens.
Here is my website with with one of the transitions I tried
I've also tried simple things like:
$(document)
.on('pjax:start', function() { $('#main').fadeOut(200); })
.on('pjax:end', function() { $('#main').fadeIn(200); })
I also ran into aenism.com/teleportation-is-scary/ in my searches for a solution and its what I currently have running on my pages.
Here is an example of it working: Demo Site
I'm not sure what the problem could be at this point.
I found a solution that works perfect for fading out and back in again. I have not tested it with other animations but it looks like it should do the trick. I hope this helps someone else!
// USER CLICKS LINK WITH PJAX CLASS
$('body').delegate('a.pjax', 'click', function() {
// CONTENT FADE OUT TRANSITION BEGINS
$('#main-content').fadeOut(300, function() {
// CALLBACK TO RUN PJAX AFTER FADEOUT
$.pjax({
url: target,
container: '#main-content',
fragment: '#main-content'
})
})
// STOP THE LINK FROM WORKING NORMALLY
return false;
})
// PJAX DOIN THANGS TO THE CONTENT FRAGMENT IDENTIFIED ABOVE
$('#main-content')
.on('pjax:start', function() {
// KEEPING THE MAIN CONTENT HIDDEN
$(this).fadeOut(0)
})
.on('pjax:end', function() {
// FADE IN THE MAIN CONTENT
$(this).fadeIn(300)
// FUNCTIONS LOADED AGAIN AFTER PJAX ENDS GO HERE
})
WOOO That suggestion worked, had to tweak it a bunch to get it to fit with my page transitions, but this is what I ended up with (works off of css3 animations):
$("body").delegate('a[data-pjax]', 'click', function(event) {
var target = $(this).attr("href");
if (contentpage == "true" || errorpage == "true") { $(".contentimage").append('<div class="pjax-loading"></div>'); }
$("body").removeClass("pjax-fadeIn").addClass("pjax-fadeOut").one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){
$.pjax({url: target, container: '#content', fragment: '#content'});
});
return false;
})
$("#content").on('pjax:start', function() {
$("body").removeClass("pjax-fadeOut").addClass("pjax-hide");
}).on('pjax:complete', function() {
$("body").removeClass("pjax-hide").addClass("pjax-fadeIn");
});
Related
I am trying to get this series of slideshows to fade in/out on scroll.
Trying to get it to do gradual fade but am not getting anywhere with this.
https://thetulip.community/Shannon-Garden-Smith
<script>
$(window).scroll(function() {
$(".image 1").css({
'opacity' : 0.5-(($(this).scrollTop())/20)
});
});
</script>
I tried this but to no avail!
My knowledge of Java is limited, so I'm not sure how to have each one fade in and out on scorll.
Any help would be beyond appreciated.
Thank you,
S
Welcome to the community.
I'm not sure which library you're using for your slideshow presentation, but jQuery has built in methods to fade HTML elements in or out. You can view them here:
https://api.jquery.com/fadeIn/
https://api.jquery.com/fadeout/
Note that each method has an optional function to call once the animation is completed, which is called once per element match. One approach could be to call fadeOut() on click, and then call fadeIn() within the fadeOut method's complete function. For example:
var images = [
"https://freight.cargo.site/w/750/i/0c4f83626e13ce4aa69fee4a84d02618c43afa3ff33d3c6bbd8fd6e265aa5538/01-03-downwrong.jpg",
"https://freight.cargo.site/w/750/i/3aa2564a6c11b13ef5c44820c69b00563e89ddd572372d52d60b6a0bfd80d1bc/01-04-downwrong.jpg"
]
var i = 0;
$(function() {
$('img').attr('src', images[i]);
});
$('img').click(function() {
$(this).fadeOut('slow', function() {
i = i === images.length - 1 ? 0 : i + 1;
$('img').attr('src', images[i]);
$(this).fadeIn('slow');
});
});
Here's a fiddle: https://jsfiddle.net/matthewmeppiel/n28hg4qj/5/
The Ember page I'm working on is to display a of grid of operators and their jobs and have that list automatically update when the user creates a new job. My current best attempt will draw pre-existing jobs on page load, but the page doesn't refresh with any new jobs created using 'saveNewJob' even though I can see the new job in the Data view of Ember Inspector.
Here's the code with some '..snip..' inserted to focus on the important parts:
routes/scheduler.js
export default ember.Route.extend({
model: function() {
return {
jobs: this.store.query('job', {
location: session.location,
date: session.selectedDate
},
operators: this.store.query('operator', {
location: session.location
}
}
},
action: {
saveNewJob: function(params) {
var newJob = this.store.createRecord('job',{
//job properties from params
};
var thisRoute = this;
newJob.save().then(function(){ thisRoute.refresh() });
}
}
}
templates/scheduler.hbs
..snip..
{{#each model.operators as |op|}}
{{operator-row operator=op jobs=model.jobs}}
{{/each}}
{{outlet}}
templates/components/operator-row.hbs
<!-- Draw the grid for the operator -->
..snip..
<!--Draw jobs over grid -->
{{#if jobs.isFulfilled}}
{{#each jobsForOperator as |job|}}
{{operator-job job=job}}
{{/each}}
{{/if}}
component/operator-row.js
jobsForOperator: Ember.computed('jobs', function() {
var opId = this.operator.get('id');
var retVal this.jobs.filter(function(item) {
return item.get('operator').get('id') === opId;
});
<!-- Append some drawing properties to each job in retVal -->
..snip...
},
..snip..
I haven't seen a need to add anything to controller/scheduler. The operator-job component is a simple div that uses the drawing properties to correctly place/draw the div in the operator row.
There are various ways for a new job to be created, but I purposefully left them out because they all end up calling 'saveNewJob' and I am able to get a console.log statement to fire from there.
One solution I've tried is adding a 'this.store.findAll('job');' at the start of the model function and then using 'jobs: this.store.filter('job', function() { })' to create the model.jobs property. That sees neither the existing jobs nor the newly created job returned despite seeing my date and location matches return true.
So what am I doing wrong here? Is there a better way to get this refresh to happen automatically? Appreciate any help you all can give.
There is function for just this case DS.Store.filter. You use it instead of query. Something like this:
let filteredJobs = this.store.filter(
'job',
{location: session.location, date: session.selectedDate},
job => job.get('location') === session.location && job.get('date') === session.selectedDate
);
I have two nested states, consisted of a parent abstract state and a child state:
.state('app.heatingControllerDetails', {
url: "/clients/:clientId/heatingControllers/:heatingControllerId",
abstract: true,
views: {
'menuContent': {
templateUrl: "templates/heatingController.html",
controller: 'HCDetailsCtrl'
}
}
})
.state('app.heatingControllerDetails.wdc', {
url: "/wdc",
views: {
'hc-details': {
templateUrl: "templates/heatingControllers/wdc.html",
controller: 'WdcDetailsCtrl'
}
},
resolve:{
hcFamily: [function(){
return 'wdc';
}]
}
})
and two controllers are:
.controller('HCDetailsCtrl',function($scope){
$scope.$on("$ionicView.enter", function (scopes, states) {
...
});
})
.controller('WdcDetailsCtrl',function($scope){
$scope.$on("$ionicView.enter", function (scopes, states) {
...
});
})
When I invoke state app.heatingControllerDetails.wdc, both controllers are created, but $ionicView.enter is only invoked on the parent controller. Any idea?
In heatingController.html, hc-details view is defined as follows:
<ion-content class="has-header" ng-show="hc">
<div ui-view name="hc-details"></div>
<div class="disableContentDiv" ng-hide="hc.state=='Online'"></div>
</ion-content>
When working with nested views, you have to use $ionicNavView events instead of $ionicView
That being said, at the last release these events are bugged, and they're currently working in a fix: Github issue
I found a work around for this. Place this in a parent of the view, or place it in the first controller that is loaded when running your application.
You can use this to observe any 'to and from' view changes. Just doing a string comparison on the url of the toState emulated ionicView.enter well enough to achieve what I needed it for. Keep in mind you need to be using UI-router to do this. Hope this helps!
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams, options){
if(toState.url == "/video/:Id"){
console.log("Leaving the view.");
}
});
I have written this simple demo component to demonstrate a problem. The component code is below
App.FocusOutComponent = Em.Component.extend({
attributeBindings: ['tabindex'],
tagName: 'focus-out',
setFocus: function() {
console.log('clicked focus-out container');
this.$().find('button').focus();
console.log('focus set to button');
}.on('click'),
focussedOut: function() {
console.log('focussedOut from outer container');
}.on('focusOut'),
});
{{#focus-out id="focus-container" tabindex="-1"}}
<button id="text-button">Test Button</button>
{{/focus-out}}
When I run this and click on the focus-out element, this is the order of the logs. Link to demo
clicked focus-out container
focussedOut from outer container
focus set to button
Now when I am trying to write acceptance tests for this with the following code.
test('test visit / and click button', function() {
expect(0);
visit('/').then(function() {
find('focus-out').click();
console.log('after click in test');
});
});
The order of the logs are different. Link to demo.
clicked focus-out container
focus set to button
after click in test
focussedOut from outer container
The focusOut log got printed at the very end instead before the after click log. I was expecting the same order for the logs with just an additional log(after click) in the end.
Im not sure if this is a bug or something wrong with my code.
I also noticed another problem while executing tests. If I have focus on the chrome dev-tools while the tests are running, the focusOut event will not trigger at all.
Some help with this is much appreciated.
the click event doesn't set focus (being a back door route). You'll need to manually set focus then click if you want the same results.
Ember's Click Helper (sends mousedown/mouseup, then click)
function click(app, selector, context) {
var $el = app.testHelpers.findWithAssert(selector, context);
run($el, 'mousedown');
if ($el.is(':input')) {
var type = $el.prop('type');
if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
run($el, function(){
// Firefox does not trigger the `focusin` event if the window
// does not have focus. If the document doesn't have focus just
// use trigger('focusin') instead.
if (!document.hasFocus || document.hasFocus()) {
this.focus();
} else {
this.trigger('focusin');
}
});
}
}
run($el, 'mouseup');
run($el, 'click');
return app.testHelpers.wait();
}
Modified Test
test('test visit / and click button', function() {
expect(0);
visit('/').then(function() {
var el = find('focus-out');
el.focus();
click(el);
console.log('after click in test');
});
});
http://emberjs.jsbin.com/lefazevozi/1/edit?js,console,output
It's also important to note, that tearing down will also call the focus out event. So the main reason you were seeing the focusout at all was because on teardown it was losing focus from the button child.
Maybe focus should be set before mousedown on the click helper in the ember test, though I'm not sure what else that might affect, or if people wouldn't generally be expecting that since jquery doesn't do that.
Looking at the Ember.js documentation, it is rather vague about when to make use of Ember.run() (my emphasis).
Normally you should not need to invoke this method yourself. However if you are implementing raw event handlers when interfacing with other libraries or plugins, you should probably wrap all of your code inside this call.
From looking through the source and reading posts on this topic, my understanding is that when you call Ember.run(), the following occurs.
The given callback is immediately run.
The run loop algorithm is executed, flushing all queues and thus ensuring bindings are synchronized, etc.
I'm trying to understand why it would be recommended to handle other libraries' events inside of a call to Ember.run(). Take the following example where I create a jQuery UI slider and handle the slide event.
<script type="text/x-handlebars" data-template-name="index">
<div id="slider"></div>
<h2>{{value}}</h2>
<h3>{{valueProse}}</h3>
</script>
App = Ember.Application.create();
App.IndexController = Ember.Controller.extend({
actions: {
valueChange: function (newValue) {
this.set('value', newValue);
}
},
valueProse: function () {
var value = this.get('value');
if (Ember.isNone(value)) {
return '';
}
if (value <= 25) {
return 'pretty small';
}
if (value <= 50) {
return 'getting bigger';
}
if (value <= 75) {
return 'whoa watch out';
}
if (value < 100) {
return 'can\'t handle it!';
}
return 'ahhhgghuarghblarp!';
}.property('value')
});
App.IndexView = Ember.View.extend({
didInsertElement: function () {
var controller = this.get('controller')
this.$('#slider').slider({
min: 0,
max: 100,
slide: function (event, ui) {
// Ember.run(function () {
controller.send('valueChange', ui.value);
// });
}
});
}
});
Here is a working fiddle: http://jsfiddle.net/ahaurw01/Kwze5/2/
Whether or not the slide event is handled inside of a call to Ember.run(), the expected behavior occurs. I'd like to understand what optimizations or insurance this offers. Either way, I see that value is getting set and valueProse is updated appropriately. Is this one of the cases the documentation is talking about when suggesting my code be wrapped in Ember.run()?
I believe the idea of running Ember.run is so that anything async events, such as event listeners from 3rd party libraries, can be synced up with the ember run loop.
I learned a ton about Ember.run and why it's useful when I started integrating QUnit into my project, because when you start testing your app, the automatic ember.run loop feature code is taken out and it's all up to you.