Is there a way in Ractive to destroy the instance (unrender event listeners, etc) but not remove the DOM changes that it made?
I'm building a one page app and the goal is that each view is its own instance of ractive. However, in some cases there is persistent data and I want to avoid a 'pop in' effect. By preserving what's in the DOM, the next ractive instance can load on page change and do its diff, removing anything that changed but preserve the things that didn't.
Thanks in advance.
Related
I have created a few variables for custom dimension on pageviews.
Pageview trigger: windowload or history change
The data is being pushed through, but it's only getting previous pages'
for example,
page/1 div class "page date" is 25th Jul, I would get undefined, but
when I click onto page/2, i would get the page/1's "page date"
function() {
return window.document.getElementsByClassName('page date')[0].innerText;
}
It seems that the history event is triggered before the corresponding page content is loaded into the DOM. This is nothing you can blame GTM for (GTM sees a history change, inspects the DOM, and grabs whatever it finds there, and that's the normal/expected behaviour).
Your solutions:
Make sure content is updated in DOM BEFORE the history event is triggered: this is something to sort out on the application side, and that may not be easily changed (if you use a framework like react it's probably best if you don't start hacking its core behaviour).
Delay the history event triggers: have a look at this solution which describes how to achieve this. Please note that solutions based on delays are never 100% reliable because there's a race condition between your delay and the loading of content, and you don't know for sure who will come first (and increasing the delay too much can cause the side effect of users changing pages in quick successions before analytics had a change to capture them).
Detect DOM changes: a more robust alternative would be to monitor the DOM for a particular element that is unique to each page (eg a <meta> element with the page ID or URL). You could use a tag to initiate the monitoring of this element when you receive the history change, and when the element actually changes it means the DOM has been updated, and you could fire your own trigger. This could be done via the MutationObserver or using a setInterval/setTimeout loop to check manually. However if the DOM is changed in several phases (blocks by blocks) this would not work (your <meta> element would have changed but not the div you're looking for), requiring you to start monitoring on a per-element or per-block level, which will be quite some work.
Push a dataLayer from your application: this would be my preferred option. I would hook into the logic of your application (you should be able to extend the routing method or the app framework should give you event listeners you can bind a custom function of yours with in which you can tell GTM that the page has been changed (eg dataLayer.push({'event': 'page_changed'});)
I have a view containing of many sub-views, which have relatively heavy CSS properties. and I need to add them(about 10-30 depending on screen-width) to browser every time user changes the sort or the category.
In android we handle this heavy task of adding many views, by using the ListView which basically does the heavy lifting once and then reuses the view later on.
I wanted to know if there is anyway in javascript to cache the view so appending them to the parent would be a lot faster.
in my performance tests, it takes about 500ms to just append the view to the parent DOM. but if there is a way to reuse a cached DOM to make things faster, it would be a lot better.
thanks in advance
I assume that in your case, one sub-view is needed at one time.
So, this library might inspire you http://nexts.github.io/Clusterize.js/
The idea is keep your whole data model in window object and render part of it (associated with sub-view) when user sort or category.
We have a web app that spits out elements server-side and some through Backbone -- and have a simple jQuery.each() statement that flips through elements on the page and adds/removes certain classes based on size of the component. I'm calling this within an "init" function, but it's obviously not working for any elements that are not on the page when loaded; within the Backbone scope.
I'd rather not re-call this function in each Backbone instance (in-case we end up adding more views that render other items needed by this function) and wanted something like a $(document).on() function to work like I do for normal clicks, hovers, etc. I haven't found any examples on how I could make this work with jQuery.each(), so would appreciate any insight on how I'd go about this.
Mutation Observers are what I'll go with.
I have jQuery on my web page, and I want to remove it programmatically.
Meaning completely unload it, destroy the object and related functions, destroy its internal memory allocations, and event bindings.
How can this be done?
I have a view that defines several events like this:
events: {
'click .js-icon-remove': 'removeFilter',
'change .select-control': 'updateFilters',
'click #btn_search': 'requestSearch',
'click #btn_add_search': 'requestSaveSearch'
}
The three click events are on buttons or links while the change event is on a dropdown. When the view first renders, all events work fine. However, when I go to a different page and then come back to this view, the dropdown event is lost. If I reload the browser, things work fine again. They even work fine multiple times, not just the first time. It's just when I re-render the view that the event binding is lost.
I have tried changing the event from a change to a click, or from the class to the element (select rather than .select-control). All things will work the first time the view is rendered and that's it.
This is getting into how event binding works in Backbone and the DOM.
When a view renders, and it's $el is added to the DOM, backbone binds the events automatically. However, once you remove the view's $el from the dom, those events will then need to be re-bound when the $el is added back into the dom. This is what your delegateEvents() method is doing.
A best practice when working in backbone is to make views disposable, eg don't keep them around after they are removed from the DOM. When you navigate away from the view, and remove it from the dom, then navigate back, you should re-instantiate the view, render it, and add it to the dom again. You can keep you models and collections around, so you don't have refetch data, but views work better when they are either left in the dom or are recreated each time they are added/ removed.
I highly recommend Marionette.js, and specifically it's region class. It saves you a lot of boilerplate code when it comes to view handling.