Backbone Marionette animate a CollectionView - backbone.js

If I have a CollectionView that is rendered and I reset the Collection with new data, how could I fade out the current collection view and then fade it back in with the new collection data?

The most straightforward way to do this, in my onion, is to call the collection.reset function ont he complete of an jQuery.animation. Say your collection lives in an element with class collection, then I would do this,
var that = this;
$('.collection').animate({ opacity: 0 }, { complete: function() {
that.collection.reset(newModels);
// Now to fade it back in
$(this).animate({ opacity: 0 });
}
});
You can run those lines from inside your view when you're ready to reset the collection. If you have a lot rendering that has to happen then you're might want to shoot off a pre-loader (a spinner, for example) inside the complete function right before the collection.reset (i.e., as soon as the images are hidden)

Related

ScrollMagic - Add class permanently, not remove when scrolling back up

All I want to do is add a class to a div the first time it scrolls into view, then keep it there. (So, I don't want to toggle it - just fire it once). I have an animation that's based on adding a class to the parent div, and even though I specified a direction, when I check it in inspector, it's still removing the class on the reverse scroll. I don't want the animation to run every time it's scrolled over, but only the FIRST time (and then stay there in the completed-animation state).
var controller = new ScrollMagic.Controller();
var scene = new ScrollMagic.Scene({
triggerElement: '#intro',
offset: 50
})
.on("start", function(e) {
if (e.scrollDirection === "FORWARD") {
$('#welcome').addClass('animated');}
})
.addTo(controller);
I did try adding a duration but it had no effect. Any suggestions?
Yes, you can add the .reverse(false) in your scene. This will make the animation happen only one time, so if you scroll back up it won't toggle the class off.
Here is an example of how to use it and a link below to a very simple demo using it. Also for even more information here is another link to the documentation.
reverse(false)
$(document).ready(function(){
var controller = new ScrollMagic.Controller();
var scene = new ScrollMagic.Scene({
triggerElement: '.title',
triggerHook: .6
})
.setClassToggle('.title', 'animate')
.reverse(false)
.addIndicators()
.addTo(controller);
});
CodePen Demo

Backbone multiple view render stack?

There are a lot of similar answers to my question, but no what I want. My problem is:
I render view in backbone router. One screen is build with three views and since rendering is async and I append every view to #content element I cant control the order of rendered elements. Any ideas? I don't want to mix rendering of views in other views. I want to control that in router class.
Without seeing your code you do a couple things. If you wanted to drop in Marionette.js, you could use events to let your router know when it has rendered it.
App = new Marionette.Application(); // somewhere before you initialize your rotuer
// in your router
var viewsToRender = 3;
var view1El = new View({model: someModel}).render().el;
var view2El = new View({model: someModel2}).render().el;
...
App.vent.on('viewRendered', function() {
viewsToRender -= 1;
if(viewToRender === 0) {
$('#content').append(view1El, view1E2, ...);
}
});
// In your views
onRender: function() {
App.vent.trigger('viewRendered');
}
onRender documentation
Or you could move the fetching of your async data outside of your views and into the router(the route I would probably take).

Marionette CollectionView: how to check whether item is added because of "reset" or "add"?

I am using Marionette's CollectionView to render a list of items with ItemViews. Whenever a new item is added, I want to run a short fade-in animation. But not when the collection is rendered initially (or the collection is reset).
Before using Marionette, I handled the reset and add events slightly differently, but I can not figure out how to do this here. I looked at the source code and it seems that addItemView is responsible for adding the child view and both addChildView (called when add is triggered on the collection) and render (for reset events) call this method.
Maybe I am missing something obvious.
This is one way of doing it:
Include these functions in your CompositeView declaration:
onBeforeRender: function(){
this.onBeforeItemAdded = function(){};
},
onRender: function(){
this.onBeforeItemAdded = myAnimation;
}
This is similar to the solution I present in my book on Marionette (https://leanpub.com/marionette-gentle-introduction/)
How it works: Marionette triggers the "before:render" before it renders the entire collection, so you can set the the onBeforeItemAdded function to do nothing. Once the collection has been rendered, set that function to animate the new item view.
Since each time the collection view adds an item view it also triggers the "before:item:added", you can define an onBeforeItemAdded function that will automatically be called when that event is triggered. This matching happens thanks to triggerMethod.
This solution should solve your problem, without your needing to add flags on the model.
David Sulc answer is pretty hacky, fadeIn should be defined within item it self, not within parent view.
Another thing is that onBeforeItemAdded() is not mentioned in documentation, so it could be for internal use and may change over time.
What I suggest is to add following to parent view, note flag parentRendered:
itemViewOptions: function() {
return {
collection: this.collection,
parentRendered: this.rendered
};
},
onRender: function() {
this.rendered = true;
}
and use that flag in onShow function inside item view:
onShow: function() {
// show visual effect on newly added items
if (this.options.parentRendered) {
this.$el.css('opacity', 0).slideDown(200).animate(
{ opacity: 1 },
{ queue: false, duration: 400 }
);
}
else {
this.$el.show();
}
}
I think that your best choice is to bind your event after the CollectionView has been rendered.
myCollectionView.on( "render", function() {
this.on( "after:item:added", executeMyAnimation );
});

Sencha touch: push component more then one time not work

I have a list with handler on list item disclose, when the user click on an item
I'm pushing a form view with the next code:
list.up('navigationview').push({
xtype: 'xEditAddFormPanel',
title: 'Edit task',
data: record.getData()
});
In the first click it's working and the navigation display the xEditAddFormPanel..
But then, after click on the back button (and return to the list screen) and then press again on list item (what triggers the above code again) - now nothing happens.
How do I display the form screen again?
I had the same problem and the reason was that the listener(s) is(are) lost the second time that you push a view into the navigator. Why? Because every time that you push a view into the Navigator the old view is destroyed, taking with it all listeners to the grave...
To get around this problem I binded the events manually whenever I create a new view that I wanted pushed:
onXButtonTap: function () {
var view = Ext.create('MyApp.view.XEntryView');
//Bind the events you need manually every time you push.
view.on('myEvent', this.onSubmitNewX);
this.getXMainView().push(view);
}
Often in Sencha, you have to manually destroy components. You may need to do something like this:
var formPanel = Ext.create('YourApp.view.EditAddFormPanel', {
title: 'Edit task',
data: record.getData()
});
formPanel.onAfter('erased', function(){
this.destroy();
}, this);
list.up('navigationview').push(formPanel);

extjs 3 - Which event is fired when extjs is completely loaded

I am using Extjs for my application. Which event/listener is fired when extjs completely loads the application (images and everything)?
I tried following but none of these worked:
body or window onload (body tag is empty)
viewport render listener
What I am doing currently: When I start the application it displays "loading" mask. Then an ajax request is fired and when it is completed, "loading" mask is removed. Following might give some idea:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
ajax_request(); // Somewhere between the code ajax request is called
// All components are loaded eg. viewport, tabpanel, button etc...
function ajax_request() {
// Other processing
Ext.ux.mask.hide(); // Hide the mask
}
});
The problem is the ajax request is taking much time now so i want to change the working something as follows:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
ajax_request(); // Somewhere between the code ajax request is called
// All components are loaded eg. viewport, tabpanel, button etc...
function ajax_request() {
// Other processing
//Ext.ux.mask.hide(); // Hide the mask - removed
}
// I want to call this when everything is loaded on the page
function everything_loaded() {
Ext.ux.mask.hide(); // Hide the mask
}
});
Any idea on this? Thanks a lot for help.
What ExtJs version are you referring to? 3.x or 4.x?
If 4.x, consider using/following the MVC Application Architecture guidelines. In that case, you want to override Ext.application.launch as described in MVC Application Architecture or Ext.app.Application
If 3.x, I guess Ext.onReady() is the best they have.
UPDATE
Based on your updated question, this is what you are looking for -
Ext.onReady(function(){
Ext.Ajax.on('beforerequest', showSpinner, this);
Ext.Ajax.on('requestcomplete', hideSpinner, this);
Ext.Ajax.on('requestexception', hideSpinner, this);
...
}); //end of onReady
showSpinner = function(){
//setup and show mask
}
hideSpinner = function(){
//hide mask
}
Reference - Ext.Ajax
base on your update.... i got conclusion that you are using Ext version 3.x.x
When I start the application it displays "loading" mask. Then an ajax request is fired and when it is completed, "loading" mask is removed
how did you call the ajax ?? why don't you hide the mask in ajax callback ?
Ext.Ajax.request({
url : "blabla",
method : "GET",
callback : function(){
Ext.ux.mask.hide();
}
});
or, mybe you want to try this one (this is what i used to show preload)
Try the afterlayout event and specify a method to execute when it's trigered
Thanks to amol and Warung Nasi 49. Although I couldn't find the best way, I manage to get almost expected result:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
setTimeout(function(){
Ext.ux.mask.hide();
}, 2000);
});

Resources