EXTJS: When I update data in XTemplate for every second in a tab panel, scrolling of the page became slow as data is continuously rendering into the template in windows XP
I have a tab panel with nearly 10 tabs. In each tab I am rendering data every second into some tables which are created using XTemplates.
I am not facing any issue with windows 7 and 10.
Could anyone please provide your suggestions.
Please find the below panel:
Ext.define('View.components.TestDataPanel', {
extend: 'Ext.Panel',
alias: 'widget.components-testDataPanel',
requires: [],
initComponent: function () {
Ext.apply(this, {
tpl: this.panelTemplate(),
data: {}
});
this.callParent(arguments);
},
panelTemplate: function () {
return new Ext.XTemplate('<div>'
+ '<h2>Test1</h2>'
+ '<table>'
+ '<tpl for="List">'
+ '<tr>'
+ '<td>{Content1}</td>'
+ '<td>{Content2}</td>'
+ '<td>{Content3}</td>'
+ '</tr>'
+ '</tpl>'
+ '</table>'
+ '</div>'
+ '<div>'
+ '<h2>Test2</h2>'
+ '<table>'
+ '<tr><th>Header1</th><th>Code</th><th>Header2</th><th>Header3</th></tr>'
+ '<tpl for="List2">'
+ '<tr>'
+ '<td>{Content1}</td>'
+ '<td>{Content2}</td>'
+ '<td>{Content3}</td>'
+ '</tr>'
+ '</tpl>'
+ '</table>'
+ '</div>',{
disableFormats: true
});
}
});
In controller :
OnData : function (data) {
var testPanel = this.getTestDataPanel();
if(testPanel && data) {
testPanel.update(data)
}
}
In each tab in the tabpanel we have these type of panels and are updated with the data every second.
The code is working fine and giving the expected results except the performance of scrollbar. Also switching between the tabs is very slow if the data is rendering continuously. Windows 7 and 10 is perfectly working as expected also no performance issues with them.
Related
I've got a node.js and sockets app that I'm using to build a SPA. A user fills out a form to create a new lobby. When they submit it, a socket event it sent to the server, the server adds the lobby, then the server emits an event to everyone with the updated list of lobbies. When this occurs, my client side JS receives the lobby list and updates a table. While viewing the browser console, this seems to work fine. I see that the the lobby info is logged in my update_lobbies function. I see that it loops through the lobbies, and I even see the html update with the new information. However, the browser doesn't seem to update the view. If I refresh the page, which requests the same lobby information, the page will update. Also, at that point, after the refresh, future lobby updates will be visually updated for that user.
socket.on('lobby list', function(data){
if(data.lobbies.length > 0){
update_lobbies(data.lobbies);
}
}
Which then calls update_lobbies():
const update_lobbies = (lobbies) => {
var lobbies_table = document.getElementById('lobbies_table');
lobbies_table.innerHTML = "";
console.dir(lobbies);
$("#lobbies_table").append("<tr>" +
"<th>" + "Name" + "</th>" +
"<th>" + "Participants" + "</th>" +
"<th>" + "Current State " + "</th>" +
"<th>" + "Actions" + "</th>" +
"</tr>");
for (var i = 0; i < lobbies.length; i++){
console.log("looping");
$("#lobbies_table").append("<tr>" +
"<td>" + lobbies[i].name + "</td>" +
"<td>" + lobbies[i].participants.length + "/" + lobbies[i].capacity + "</td>" +
"<td>" + lobbies[i].state + "</td>" +
"<td>" + "<button id=\"join_lobby\" value=\"" + lobbies[i].name + "\">Join</button>" + " | " + "<button id=\"spectate_lobby\" value=\"" + lobbies[i].name + "\">Spectate</button>" + "</td>" +
"</tr>");
}
}
One thing that may be related is that I have a e.preventDefault(); in the form to prevent the page from reloading when I submit the form. Removing this obviously 'fixes' the problem because I'm doing a reload, but I don't want to have to reload the page to get the browser to update the view. I'm not exactly storing state information yet, so reloading isn't yet an option anyway.
I was making a stupid mistake. If the page loaded and there were no lobbies, I was hiding the table. I was just forgetting to show it when lobbies were added.
I have a Kendo Grid with a column definition as follows:
columns.Bound(c => c.Id).Title("ID #").Width("150px").ClientTemplate("#=showDetails(data.Id)#");
I'm calling a method showdetails that returns a link to open the details in a new page.
I need some help figuring out how to build the link.
This is my showDetails method:
function showDetails(data) {
var returnText = "<a href='/Detail/Index/" + data + "'>" + data + "</a>";
return returnText;
}
How do I modify it, so, the details page is opened in a new window?
add:
target="_blank" to return statement
var returnText = "gt a href='/Detail/Index/" + data + "'>" + data + "</a>";
to:
var returnText = "gt a target='_blank' href='/Detail/Index/" + data + "'>" + data + "</a>";
Reference link: https://www.w3schools.com/tags/att_a_target.asp
I would like to achieve 2 things with this Code I have been working on so not sure if to separate the Questions:
JS:
function listPosts(data) {
postlimit =
var output='<ul data-role="listview" data-filter="true">';
$.each(data.posts,function(key,val) {
output += '<li>';
output += '<a href="#devotionpost" onclick="showPost(' + val.id + ')">';
output += '<h3>' + val.title + '</h3>';
output += '<p>' + excerpt + '</p>';
output += '</a>';
output += '</li>';
}); // go through each post
output+='</ul>';
$('#postlist').html(output);
} // lists all the posts
Questions:
1: I would like to limit the number of Dynamic List Posts returned to 8
2: While I limit the displayed items, I want to add a 'More...' text at the bottom so another set of 8 items is appended to already displayed list.
I am already trying out some codes but was hoping to get some guidance
function listPosts(data, postlimit) {
var $output = $('<ul class="posts" data-role="listview" data-filter="true">');
$.each(data.posts,function(key, val) {
$("<li>", {id: "post_" + val.id})
.append([
$("<h3>", {text: val.title}),
$("<p>", {text: val.excerpt})
])
.appendTo($output);
return (postlimit-- > 1);
});
$('#postlist').empty().append($output);
}
// exemplary delegated event handler
$(document).on("click", "ul.posts h3", function () {
$(this).show();
});
later ...
listPosts(data, 8);
Notes:
from $.each() you can return true or false. If you return false, the loop stops.
Try not to build HTML from concatenated strings. This is prone to XSS vulnerabilities that are easy to avoid. jQuery gives you the tools to build HTML safely.
Generally, for the same reason, try to avoid working with .html(), especially if you already have DOM elements to work with.
Don't use inline event handlers like onclick. At all. Ever.
I am answering you on basis of pure logic and implementation of logic. there could be API stuff for it , but I don't really know. Secondly; It would be a good solution to find some jQuery plugin if you don't have any problems with using jQuery.
call the function onMoreClick() upon clicking the More... html item
var end = 8;
var start = 1;
function onMoreClick()
{
start = end
end = end+8;
listPosts(data)
}
function listPosts(data) {
postlimit =
var output='<ul data-role="listview" data-filter="true">';
var i = start;
$.each(data.posts,function(key,val) {
if(i<end && i >=start){
output += '<li>';
output += '<a href="#devotionpost" onclick="showPost(' + val.id + ')">';
output += '<h3>' + val.title + '</h3>';
output += '<p>' + excerpt + '</p>';
output += '</a>';
output += '</li>';
i++;
}
}); // go through each post
output+='</ul>';
$('#postlist').html(output);
} // lists all the posts
I seem to have a memory leak in IE9. It works just fine in Chrome. The memory leak is on the client machine. I left this page open for days in chrome and no leak.
Using jquery 1.9.0, signalr rc2
This page uses signalr and refreshes it's contents every 5 seconds with what comes from the server.
I have four tabs/divs that do this.
proxy.on('newRequests', function (data, updatetime) {
newrequestupdatetime.text('Last updated: ' + updatetime);
numberofnewrequests.text('Number of cases found: ' + data.length);
numberofnewrequeststab.text('(' + data.length + ')');
var h = '';
$.each(data, function (i, val) { h += '<li>' + val.Ref + ' ' + val.Type + '</li>'; });
newrequests.html(h);
});
newrequests is an ul on the page which I initialized like this
var newrequests = $('#newrequests');
in
$(function () {});
Not really sure what is the cause.
I can make it a lot worse by doing this.
newrequests.empty();
$.each(data, function (i, val) { newrequests.append('<li>' + val.Ref + ' ' + val.Type + '</li>'); });
I'm guessing that it has something to do with the last line of code, that puts the new html inside the ul tag.
Try changing the line into this (old code):
document.getElementById('newrequests').innerHTML = h;
See also: jQuery - Internet Explorer memory leaks
I am working on a website that uses infinite scroll. There is a function called is_element_in_view() that gets executed on these 3 events:
scroll
load
resize
The function does exactly what it's called, it checks to see if an element with a loading gif image is in view and if so it fires an ajax request to get content from the server.
The server sends back a json object that looks like this:
[{
"url": "\/embed\/182926\/some-slug",
"thumb": "http:\/\/cdn.site.com\/91\/26\/a62c1ad74327321dab78bb194c130da5.jpg",
"type": "video",
"is_original": false,
"is_prank_news": false,
"title": "Hello World",
"description": "\t<p>Enjoy this video!<\/p>",
"teaser": "Click Me!",
"finder": "Found by <strong>Jim<\/strong> yesterday",
"likes": "2 likes",
"ad_img": null,
"media_stats": "<div class=\"media-status\">2000 views<\/div>"
},
more objects...]
There's only one object in this response for clarity sake but in reality I get back 20. This is how I'm building out the html from the json data:
$.ajax({
url: '/some/ajax/url',
type: 'get',
data: 'somedata',
dataType: 'json',
success: function(response) {
if(!$.isEmptyObject(response)) {
for(var i = 0; i < response.length; i++) {
if(response[i]) {
var item = response[i];
var title = item.title.replace(/\\"/g, '"');
var media_label = '';
var item_description_teaser = '';
var likes = '';
var ad_image = '';
var media_stats = '';
if(item.description) {
// description
item_description_teaser = '<div class="description">' + item.description.replace(/\\"/g, '"');
// teaser
item_description_teaser += (item.teaser) ? ''+ item.teaser.replace(/\\"/g, '"') +'<img src="images/teaser-arrow.png" alt="" /></div>' : '</div>';
}
// media label
if(item.type == 'article' && item.is_prank_news || item.is_original && item.is_prank_news) {
media_label = '<span class="media-label prank-news-network">Prank</span>';
}
else {
if(item.type == 'article') {
media_label = '<span class="media-label article">Article</span>';
}
else if(item.is_original) {
media_label = '<span class="media-label original">Original</span>';
}
}
// likes
if(!settings.hide_likes) {
likes = '<span class="likes">' + item.likes + '</span> | ';
}
// ad image
if(item.ad_img) {
ad_image = '<img src="'+ item.ad_img +'" alt="" class="ad-img" />';
}
block += '<article class="block">' +
'<div class="inner-left">' +
media_label +
'<a href="'+ item.url +'" title="" class="thumb">' +
'<img src="'+ item.thumb +'" alt="" width="198" height="111" />' +
'</a>' +
'</div>' +
'<div class="inner-right">' +
'<a href="'+ item.url +'" title="" class="title">' +
title +
'</a>' +
item_description_teaser.replace(/\\"/g, '"') +
'<div class="media-stats">' +
likes +
'<span class="finder">'+ item.finder.replace(/\\"/g, '"') +'</span>' +
'</div>' +
ad_image +
'</div>' +
item.media_stats +
'</article>';
}
}
$('#content').append('<div class="page page-'+ page_num +'">' + block + '</div>');
// update page count
page_num++;
// clear previous listings
block = '';
}
else {
$('#content').append('<div class="page page-1"><p class="nothing-to-show">Nothing found...</p></div>');
}
},
error: function() {
alert('error');
}
});
As you can see I put everything in one giant string stored inside the variable block. I append data to this string with every loop and append it to the page outside the loop at the end.
I feel like there is a faster way to build html from js. I read somewhere a while ago that building giant strings like I'm doing isn't as efficient as some other method the article described that I forgot. So what's the faster way to do this?
Store the blocks in an array say blocks, then
$('#content').append(blocks.join(""));
Edit: that wasn't what the OP wanted. I guess the problem is appending the stuff each time the event is triggered.
I'd say to create a DocumentFragment, put the new stuff in it, then appending to $("#content"). Unfortunately, DocumentFragments don't support innerHTML.
So, create a dummy element, fill it and then put its child nodes into the container:
var dummy = $("<div>").html(block), content = $("#content");
$.each(dummy.children(), function(i, c) {content.append(c);});
Adding html elements to the DOM represents a big performance penalty so it is better to create a big string and append it at the end, this post explains it really well
For most of your uses, the method of creating one really long string and appending it at the end will be the best choice, as it makes the best use of the trade offs of code legibility, ease of programming, and speed.
You could have your server return the values already marked-up in HTML, then:
$('#content').append( response );
You can then handle all of your looping and filtering server side, cutting down on the amount JS in your document.