I'm attempting to use the mediaelement.js player in a backbone.js site and I'm having trouble removing video/audio players manually when I move in and out of the various routes I have set up.
Let's say I have two videos on my page. When I move away from this page, these two videos are still preserved in memory:
> mejs.players
> [object, object]
When I return to the page, the original two videos are still in memory and an additional 2 videos are added to the players object:
> mejs.players
> [object, object, object, object]
In fact, every time I leave the page and then return, an additional 2 players are added to the mejs.players object.
Is there a way to clear/remove all of the players manually?
I've tried the following:
mejs.players[0].remove()
This seems to remove the player controls from the page, leaving the HTML5 video player. However, the player still persists when I check mejs.players. I could be wrong, but this doesn't seem optimal for performance.
Since this is for a Backbone site (which has UnderscoreJS), this would work, you can use _.keys() instead of Object.keys()
if (mejs) {
var players = _.keys(mejs.players);
_.each(players, function(player) {
mejs.players[player].remove();
});
}
first delete mejs.players and create new mejs.players array
if (mejs) {
delete mejs.players;
mejs.players = [];
}
Related
I am working on this hobby project of creating sticky notes, by clicking on the x on the notes, you can see the note doesn't disappear as expected but the contents inside that note is gone but the rest of the notes also change, why is that, this is the link to codesanbox, thanks!!
https://codesandbox.io/s/epic-hugle-1o2o2
You need to use a key for each item when rendering arrays of elements.
Read https://reactjs.org/docs/lists-and-keys.html for more details.
Here is a fix to your code: https://codesandbox.io/s/keen-snow-yqitv
Basically add a key when creating a new note and use it when rendering the items.
add = note => {
var temp = this.state.notes;
temp.push({ key: Math.random().toString(), note });
this.setState({ notes: temp });
};
(the example code just uses Math.random to generate the key, which is not safe for production use. See https://github.com/kelektiv/node-uuid#readme for a better approach)
You might also want to review your code to not mutate the state.
In my angular app, there are two pages (list & checkout). In the list page the user could search for an item and the searched item will be displayed and then the user can select the item and continue to checkout.
From the checkout page the user could return back to list page, and at that time all the items in the list page should be same as how it was left before.
For implementing this feature, my code is
on moving from list page to checkout page, all the scope data are stored in a service
returnsService.setScopeData($scope);
And on returning back from checkout page to list page, this saved data are retrieved from service and assigned to scope variables.
var restoreScopeData = returnsService.getScopeData();
if (restoreScopeData) {
for (var key in restoreScopeData) {
if (key.charAt(0) != '$') {
$scope[key] = restoreScopeData[key];
}
}
}
This works fine to an extend, and I can see the list page same as how I left it.
But the problem is, now I'm not able to search for new item in the list page.
When ever a search happens, the items are populated to $scope.listSearch and they are displayed in html {{listSearch}}.
In the error case also,
I can see the new search data getting assigned to the $scope.listSearch, but the HTML binding is not happening.
I tried calling $scope.$apply() after the search assigning, but still not working.
Storing complete scope isn't good idea. You can just store the vars you need. Also, you can use localStorage for this.
As I understood, making new call is not an option, so you can try use $timeout.
$timeout(function() {
$scope.listSearch = myValue;
});
Instead of doing this, you may for localStorage or sessionStorage as suggsted by John.
You may check below link for example
https://www.codeproject.com/Articles/1015515/Working-With-Client-Side-Local-Storage
I am working on a News Feed that is similar to Facebook News Feed. I am implementing it in the following sequence:
When app is started, get everything, but only push two item to show.
The user can scroll down to see more and I will add more to the list.
If there are any new items, the user needs to pull to refresh to add the new ones.
The only problem I have right now is that each time an item is added, $firebaseArray automatically adds the new item to my array that I do not want snyc changes (I want to query once, get a set list). I was wondering if anyone would know how to prevent the auto update?
Look into .once this will allow you to get the data just once: https://firebase.google.com/docs/reference/js/firebase.database.Query#once
Instead of binding directly your $firebaseArray to the view, clone it to a scope (or controller) property that will be bound to the view. Factorize this process in a function you can call when the user pull-reloads so the the $firebaseArray is re-created.
A more appropriate approach would be to use Firebase's http api, with the angular $http service.
Edit: to clone the array to a scope var, try the following:
var allEvents = $firebaseArray(queryOfeverything);
allEvents.$loaded()
.then(function(events){
$scope.allEvents = angular.map(events, function(event) {
return event; // you may want to replace this line - I am not very familiar with firebase.
})
});
Let's suppose a function called refreshList aiming to call a REST API to retrieve a JSON array containing items.
$scope.refreshList = function () {
// assuming getting the response object from REST API (Json) here
$scope.items = response.data.listItems;
}
And a basic ng-repeat on the HTML side:
<div ng-repeat="item in items track by item.id">
Then, I added a onPullToRefresh function, triggered by this directive, aiming to trigger a refresh of the whole list.
$scope.onPullToRefresh = function () {
$scope.items = [];
$scope.refreshList();
}
It's HTML is:
<ion-refresher on-refresh="onPullToRefresh()">
</ion-refresher>
The issue is that some pull-to-refresh (while scrolling to the top) can crash the app randomly...
Thus, I decided to alter the $scope.onPullToRefresh function like this:
$scope.onPullToRefresh = function () {
//$scope.items = []; commenting this line, causing the potential memory leak and the crash of the app
$scope.refreshList();
}
With this update, the app never crashes any more on my iOS device :)
However, I don't figure out what is the main difference by keeping the line emptying the array.
Does it impact directly the ng-repeat directive, causing some mess since the REST API's promise would reassign the content immediatly?
Indeed, Xcode IDE (since cordova app) indicated this error before applying this fix: EXC_BAD_ACCESS.
What might be the reason of this behavior?
I'm pointing out that Ionic (the framework I'm using) is fully tested with Angular 1.2.17 currently, so I'm using this version.
This probably isn't the greatest answer as I'm not 100% certain, but I would suggest it has something to do with the digest.
The ng-repeat likes to work with the one array and not be cleaned out between refreshes. It's designed more to allow you to dynamically add/remove items from the array and the view is updated accordingly in the digest loop. You can do some nice animations for items being added and taken away etc with this.
So when the digest arrives, you've scrapped the array it was watching and thrown a new array into the memory it had.
Try, instead of clearing the array $scope.items = [];, to .pop() each item in the array while it has length.
it will have very little impact to do it this way. Otherwise, the best "Angular" way for the ng-repeat is to do it by just adding the new items to the array and remove any that are now gone.
Using Sencha Touch (2.2) with Sencha Architect 2
I have a tree structure in which I navigate.
The nodes are Elements and elements can either be a folder or a leaf.
To display the elements on my Ext.dataview.dataview (LIST), I use a store (storeID: 'elementstore') and Ext.dataview.component.Dataitem.
Here is my code to fill the LIST at first and everytime we open a folder to go deeper in the tree.
Filling the store for the first time, disable event so update() is not
called twice has I will be switching to this view right after the
creation of it. It works well and give back the desired result. I have
in my LIST the first level of Folders and Leaf displayed.
This is fired directly in the list with an onItemTap Event
var EStore = Ext.getStore('elementstore');
EStore.removeAll();
EStore.suspendEvents();
EStore.add(record.get('arrElement'));
EStore.resumeEvents(true);
Emptying and refilling the store with the reached level of the tree.
This is fired directly in the LIST with an onItemTap Event
if(record.get('strUIType') === 'folder')
{
INDEX_STACK.push(index);
store = Ext.getStore('elementstore');
store.removeAll();
store.add(record.get('arrElement'));
}
What is wrong is when I try to go backward, going up in my tree. Here
is the code which is located in a Sencha Controller.
It actually does not go back one level but back at the top level. ACTIVE_PROJECT is the
index of the active tree which are all located in my project store.
var popped =INDEX_STACK.pop();
var tab = tabpanel.getParent().getParent().getParent().getComponent('projects_Tab');
if(popped === undefined)
{
tab.setActiveItem(0);
}
else
{
var eStore = Ext.getStore('elementstore');
eStore.removeAll();
//Crashes!
eStore.add(Ext.getStore('projectstore').getAt(ACTIVE_PROJECT).get('arrElement'));
}
Has you see the eStore.add(....) is the crashing line on which I get the following error :
Uncaught TypeError: Cannot call method 'indexOf' of null sencha-touch-all.js:21
Ext.Array.contains.e
Ext.Array.include
Ext.define.join
Ext.define.insert
Ext.define.add
Ext.define.onMain_TabsTap (----Yep this line is my code the rest is sencha touch...
Ext.define.doFire
The only thing I achieve to add to the store in this controller is an empty Ext.create(CarboZero.model.Element). I can not get anything from my active project.
Is there something wrong with removing and readding? Is my store getting corrupted from how I'm using it? I have been working on that for about 2 days without getting anything to work properly...
EDIT TO THE QUESTION
I just set in my Element store the destroyRemovedRecords to FALSE.
Everything works, but I don't understand ANYTHING on why it corrected the problem with my particular structure... WHat is the remove() doing exactly???
Set Element store's property to the following
destroyRemovedRecords : false
Solve the problem, still can't explain why.
I had the same issue. In my case, the caching became full. On the leaf models, you could set useCache: false to prevent the data to get cached. That fixed my issue.