Currently, the only solutions I have found for animating between routes is just fade out the current page onBeforeAction and fade in the new page onAfterAction. But this is just lame.
I want to try to execute some really sleek transitions like these.
I believe this requires having multiple pages rendered on the page at the same time, but that seems very resources intensive and doesn't even seem to use iron router at all.
Any ideas how I can implement this?
I use a solution like this http://meteorpad.com/pad/5kii9SRbbnjiTHeQe
The MeteorPad doesn't allow to use IronRouter, so my example doesn't use it. In IronRouter you can use action() method to set "currentPage" session variable and always render "transitioner" template. Something like this:
Router.map(function() {
this.route('home', {
path: '/',
action: function() {
Session.set('currentPage', 'home');
this.render('transitioner');
}
});
this.route('about', {
action: function() {
Session.set('currentPage', 'about');
this.render('transitioner');
}
});
});
I use a wrapper for this. It also helps me to define transition styles and directions.
And be careful with subscriptions/unsubscriptions, becouse previous page will react to subscriptions changes before the transition is compelete!
This question seems to get asked a fair amount and there is no definitive solution, and a lot of answers out there are getting stale, or at least not applicable to the latest iron-router and Meteor 1.0.
I just did a bunch of searching around for the best answer and at least today it seems the packages for this are:
https://github.com/percolatestudio/momentum-iron-router/
and
https://github.com/ccorcos/meteor-transitioner/
The former hasn't been updated in a little while but has lots of commits. The latter has few commits but may be being actively worked on.
I'm in progress on trying them out so if I remember I'll check back in.
Related
On my website (which is under construction) I'm using "Before-After MultiX Slider". It's working fine, but I'm trying to have all the separators "collapsed" on the right (or left).
For example here
I've tried to use css to change width of some classes as follows:
.wmg-image.wmg-image-3.first.ui-resizable {
width: 91.6379%!important;
}
.wmg-image.wmg-image-2.ui-resizable {
width: 95%!important;
}
.wmg-image.wmg-image-1.ui-resizable {
width: 98.3621%!important;
}
If I don't use !important nothing happens. If I use it, I get what I want
but the slider stops working and the images don't resize by scrolling separators.
Any idea on how to achieve this?
I can't find any failure there and digged a little deeper into the problem... Therefore I post a second answer, because the nature of the problem is somehow different after all, the code is working but not as expected for the following reason:
If you load scripts async the page will continue to render while the scripts are still loading, so it is possible that other none async scripts comming afterwards will start to load earlier than some async ones still in query...
Here we don't have async ones, BUT it seems to be like even if the async keyword is not present though the scripts will come in the query one after an other depending on their order nevertheless the server will load round about 3 or 4 scripts parallel!
-> So it happens that shorter scripts may be finished to load before longer ones allthough they've started to load later...
On my research I could not find a definite solution for that problem, because it simply seems to be quite hard to control that loading process in detail! (You i.e. can find some topics about that phenomena here on the board...)
I will present some different approaches, you will have to test them yourself, because I don't have that slider PlugIn so I could try:
Solution 1:
Try to use the "defer" keyword, this should be so to say the opposite of "async" and cause scripts to be not loaded before the page is parsed completly, but sadly I'm not sure if that works, never used it before and it sounds like it is the same as using "document.ready" which is not working in this case...
Important thing is that you must insert the script externally otherwise the keyword won't do anything, i.e:
<script src="demo_defer.js" defer></script>
Solution 2:
A surely working solution would be to add our script as a callback to the call of the slider script, but I guess that this is no suitable solution here because you'll have to change the PlugIn code which is not update safe!
Solution 3:
Maybe you can play with a timeout to make sure that the execution will start later, but the problem is that you cannot really know how long this timeout must be! (i.e. have a look here: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
WORKAROUND:
I thought up a way to get around that problem, but as said before the code is untested, maybe try that and give me a notice when you have included this script, so I can have a look how it works...
In this way it is supposed that a class which does the positioning with the !important-statement is added and then removed on the first click, just then the elements are positioned again without !important and of course after that on every further click the positioning won't be manipulated again!
function sr_custom_width_for_slides()
{ ?>
<style type="text/css">
.notClicked .wmg-image.wmg-image-3.first.ui-resizable {
width: 91.6379% !important;
}
.notClicked .wmg-image.wmg-image-2 {
width: 95% !important;
}
.notClicked .wmg-image.wmg-image-3 {
width: 98.3621% !important;
}
</style>
<script type="text/javascript">
jQuery( document ).ready(function() {
var firstClicked = false;
jQuery(".wmg-before-after").addClass("notClicked");
jQuery(".wmg-before-after").click(function() {
if ( !firstClicked ) {
jQuery(".wmg-image.wmg-image-3.first.ui-resizable").css("width","91.6379%");
jQuery(".wmg-image.wmg-image-2.ui-resizable").css("width","95%");
jQuery(".wmg-image.wmg-image-1.ui-resizable").css("width","98.3621%");
jQuery(".wmg-before-after").removeClass("notClicked");
firstClicked = true;
}
});
});
</script>
<?php }
add_action( 'wp_footer', 'sr_custom_width_for_slides', 1000 );
EDIT REGARDING YOUR LAST COMMENT:
I checked the site again and in my case it sadly does not work at all, because the click event is never fired! I guess that the JS code of the PlugIn binds some events which maybe stop our script from working... (See the function "stopPropagation()" for more infos.) So my final clue is to simply bind another event which hopefully is not manipulated by the PlugIN in that way! As far as I can see this could be "mouseenter" or "mouseover"...
So just change
jQuery(".wmg-before-after").click(function() {
...
});
to
jQuery(".wmg-before-after").mouseover(function() {
...
});
the problem is quite simple... The width is set inline via js, so this will override any changes you made in your css file!
If you set the styles with an !important-statement it will work, but the sliders script cannot set the new width anymore...
So after all the most easy way to achieve what you want is to insert a small script which sets the styles AFTER the slider scripts have been loaded, so maybe at the very bottom of the footer of the page after the "wp_footer" call, because most plug ins enter their js over this hook, somehow like this:
<script>
jQuery(function() {
jQuery(".wmg-image.wmg-image-3.first.ui-resizable").css("width","91.6379%");
jQuery(".wmg-image.wmg-image-2.ui-resizable").css("width","95%");
jQuery(".wmg-image.wmg-image-1.ui-resizable").css("width","98.3621%");
});
</script>
I can't test it, but I'm quite sure that this will work, if the script is inserted at the correct position! :)
EDIT: I made a quick test via the console of the FF inspector and it works as expected, but as mentioned above, if the slider script will load later than this script it won't work at all!
Is there a way with EmberJS to show a loading template somewhere when something in my page is loading something?
For example, I have a page with many many songs artists, and each of them have many many songs. I load the page of the artists, and good, but in background I'm loading info about songs of everyone. I simply need a loading spinner somewhere that says to me the site is loading something (for example, there is in "Network" tab of Chrome Developer Tools something pending...)
how to do that in such an elegant Emberjs way?
You can observe the isPending property of Ember.PROMISEPROXYMIXIN like so:
{{#if artist.songs.isPending}}
loading...
{{/if}}
As far as I know (and based on a quick perusal of the API docs) Ember doesn't provide a built-in way to achieve this. Unless I'm wrong, this means you'll need to implement request state tracking yourself.
You could do this in Ember's adapter layer (e.g. add code in app/adapters/application.js), but the simplest solution might be to just work with jQuery directly. There are a few APIs you can use:
jQuery.active, which indicates the number of outstanding requests
ajaxStart and ajaxStop
I'd recommend creating an Ember.Service to track this state-- then you can inject it in any Controller or Component that needs to render a template based on this info. Your Service could look like:
import Ember from 'ember';
export default Ember.Service.extend({
init() {
this._super(...arguments);
const invalidateRequestInProgress = () => {
this.notifyPropertyChange('dummyProperty');
}
$(document).ajaxStart(invalidateRequestInProgress);
$(document).ajaxStop(invalidateRequestInProgress);
},
requestInProgress: Ember.computed('dummyProperty', function() {
return Ember.$.active !== 0;
}),
});
I haven't tested this code, so I'm not sure if it'll work in practice :)
Needless to say, my experience with Meteor is lacking. I come from a Rails background, where you can do a lot more logic (and magic) in your views than Meteor.
The situation: I've got some routes that look like /things/:_id, and I've named that route 'thing' because it shows only one thing of a user's many owned things:
FlowRouter.route('/things/:_id', {
name: 'thing',
action() {
BlazeLayout.render('appPage', {app: 'thing', sidebar: "thingsListOnThing", header: 'thingTitle'});
}
});
As you can see, I'm also loading a template I've built to list all of the user's owned things on the sidebar for easy navigation. That template, thingsListOnThing is the target of this question.
Get the gist? I'm able to mark the route that dislays a template with a complete list of a user's things as active using zimme:active-route like so:
// A list of all a user's things
<div class="{{isActiveRoute name='things' class='is-active'}}">
List of Things
</div>
This package is great, but it won't help me with routes that look like /things/:_id because, then every link to each individual thing would be is-active on any thing page, not just the one where the current path's :_id matches the _id of the active thing.
I'm really kind of stuck here. My first guess would be to use template helpers, but I'm confused as to where to get started with that.
If need be, please as me to upload any piece of my code you require. I figured it's such a generic question that you guys probably don't need to see all of my code to understand what I'm trying to accomplish.
Using: zimme:active-route
Template Helpers
Template.listOfThings.helpers({
activeListClass(page) {
const active = ActiveRoute.name('thing') && FlowRouter.getParam('_id') === this._id;
return active && 'active';
},
});
Template HTML:
<a class="{{isActivePath 'thing'}}" href="/things/{{_id}}">
<div class="thingListItem {{activeListClass page}}">
{{title}}
</div>
</a>
My site works fine when the data is in a template, but once I try to route to it using iron:router, a background image and most remaining content no longer appear. (Some of the content still appears with working css, JS components so I know that those files are being read. Also, when inspecting the element, all the text, images are still visible in the code, but not the website.
This works fine (index.html):
<body>
{{>home}}
</body>
This adds another {{>home}} section, but the new section is having issues rendering as explained above (router.js):
Router.map(function() {
this.route('home', {path: '/'});
});
Are you on the latest iron:router? I had a similar problem, and inquired about it in this pull request:
https://github.com/iron-meteor/iron-router/issues/1051
Latest response indicates this should be fixed now!
You've followed the wrong tutorial :( There are plenty of tutorials and articles out there explaining to define routes like you did.
However, the Iron Router project page explains how to define routes differently.
For more information on routes, have a look at this article about Iron Router as well.
Fixed: problem was not with iron:router but rather that not all elements were loaded into the page yet. Document.ready() works fine when I directly called template.
Issue is that when iron:router loads the template, the new page elements are being loaded after the JS files were already called (JS that animates the images/text in).
Solution: use rendered instead of document ready:
Template.MyTemplate.rendered = function(){
}
I am using findOne just to fetch one certain element for my collection.
However, when I do that, all my template functions containing those collections are re-run and the content refreshed. The content is similar, the problem is I am applying styles to some of those elements, and these updates just reset everything as well. More importantly: those refreshes are completely useless.
For example, I have this template:
Template.content.cars = function () {
alert("I AM RERUN!");
return Cars.find();
};
And in another function, I am doing this:
Cars.findOne({ _id: Session.get('current_car') }, {});
Why would be the first template re-run? Am I doing something wrong?
I'm not sure why your first template would be re-run: are you sure something else isn't going on?
But as a general non-answer to your question: you should expect that a template which depends on the entirety of a collection will be re-run many times (for instance as the data loads incrementally when the page first renders). With meteor you need to write your HTML/CSS in such a way that this re-rendering won't cause problems.
Without knowing more about your problem I can't really say more than that.