ngInfiniteScroll is being called more than it needs to - javascript

I have the following unordered list that uses ngInfiniteScroll:
<ul class="list-group" infinite-scroll="loadMore()">
<li ng-repeat="post in posts | filter:search" class="list-group-item isteacher-{{post.isteacher}}"><h4>{{post.title}}</h4> by {{post.author}} on <small>{{post.date}}</small></li>
</br>
</ul>
My loadMore() function queries the database with the offset. The offset being the number of items that are loaded thus far. I've tested this by hand and it works fine.
$scope.offset = 0;
$scope.posts = [];
$scope.loadMore = function(){
$http.get('/getposts?offset='+$scope.offset)
.success(function(data){
var newList = data.post_list;
if(newList.length>0){
for(var x=0; x<newList.length; x++){
$scope.posts.push(newList[x]);
}
$scope.offset+=newList.length;
}
});
}
The database has a fetch limit of "10" everytime it is queried, and accepts an offset. I have a dataset of 11 posts, just to test. If it works, it should load the first 10 when the page loads, and the 11th one as soon as I scroll. While this works some of the time, it breaks most of the time. What I mean by it breaking is that it loads the last post 3-4 times. I tested it by logging $scope.posts.length every time the function is called. When the page loads, the length is 10, but as I scroll down it keeps adding the last element multiple times. Any help would be great!

The problem is, you start the http get request and waiting for the response. Meanwhile you are scrolling up and done and your function would be called again. That could be the reason why the last posts are loaded multiple times. However, and if the query was successful than you are adding newList.length to your offset. Possible solution for this problem:
$scope.offset = 0;
$scope.posts = [];
$scope.isBusy = false;
$scope.loadMore = function(){
if($scope.isBusy === true) return; // request in progress, return
$scope.isBusy = true;
$http.get('/getposts?offset='+$scope.offset)
.success(function(data){
var newList = data.post_list;
if(newList.length>0){
for(var x=0; x<newList.length; x++){
$scope.posts.push(newList[x]);
}
$scope.offset+=newList.length;
}
$scope.isBusy = false; // request processed
});
}

Related

Creating whole new view based on current user's group sharepoint 2013

I am trying to generate a view based on the current user's group name. Group Name I am gathering from the custom list.
My question is how to apply the gathered group name to 'Group Name' column as a view parameter.
The only solution I figured:
I have created a view with a parameter.
I have added an HTML Form Web Part into the same page and connected it to the list view (sending the value to the parameter via web part connection). Then with a window.onload function I gather the current user's group name and pass this value via Form Postback function. But since the Postback function triggers full page reload, it falls into the endless loop of form submission > page reload.
Another way I have tried is attaching a click event listener to the BY MY GROUPS tab and it works perfectly, but the only disadvantage is that the page reloads each time user clicks on this tab, which I would like to avoid.
So the solution that I need is a way to post the form without a page reload.
Another option suggested here is to use CSR (client side rendering), but that has its own problems:
This code does not work as it is supposed to. In the console it shows me correct items, but the view appears untouchable.
Even if it worked, the other column values are still viewable in the column filter, as in this screenshot:
So, it seems that CSR just hides items from the view (and they are still available). In other words its behavior is different from, for example, a CAML query.
Or am I getting it wrong and there's something wrong with my code?
Below you can find my CSR code:
<script type='text/javascript'>
(function() {
function listPreRender(renderCtx) {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() {
var currUserID = _spPageContextInfo.userId;
var cx = new SP.ClientContext('/sites/support');
var list = cx.get_web().get_lists().getByTitle('Group Members');
var items = list.getItems(SP.CamlQuery.createAllItemsQuery());
cx.load(items, 'Include(_x006e_x50,DepID)');
cx.executeQueryAsync(
function() {
var i = items.get_count();
while (i--) {
var item = items.getItemAtIndex(i);
var userID = item.get_item('_x006e_x50').get_lookupId();
var group = item.get_item('DepID').get_lookupValue();
if (currUserID === userID) {
var rows = renderCtx.ListData.Row;
var customView = [];
var i = rows.length;
while (i--) {
var show = rows[i]['Group_x0020_Name'] === group;
if (show) {
customView.push(rows[i]);
}
}
renderCtx.ListData.Row = customView;
renderCtx.ListData.LastRow = customView.length;
console.log(JSON.stringify(renderCtx.ListData.Row));
break;
}
}
},
function() {
alert('Something went wrong. Please contact developer')
}
);
});
}
function registerListRenderer() {
var context = {};
context.Templates = {};
context.OnPreRender = listPreRender;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(context);
}
ExecuteOrDelayUntilScriptLoaded(registerListRenderer, 'clienttemplates.js');
})();
</script>

Angularjs infinite scroll fails to load additional records

I'm a beginner to angularjs and ionic and i'm implementing infinite scroll, with my current script when it loads the second set of records, it not able to capture the lastid and the new generated records to pass it.
For example when the page loads for the first time (displaying 2 records at a time) and the lastid is 10 when a user scroll to the bottom of the page it passes the lastid 10 to get the next set of records when you scroll down again, it passes that same lastid of 10 instead of 8
$scope.lastid = "";
$http.get('http://localhost/myapp/feeds.php').success(function(data){
console.log(JSON.stringify(data));
$scope.feeds=data;
$scope.lastid = $scope.feeds[$scope.feeds.length - 1].user_id;
});
$scope.addMoreItem = function(){
$http.get('http://localhost/myapp/feeds_more.php?user_id='+$scope.lastid).success(function(data){
$scope.temp=data;
for(var i = 0; i < $scope.temp.length - 1; i++) {
$scope.feeds.push($scope.temp[i]);
if(i == $scope.temp.length - 1){
$scope.lastid = $scope.temp[i].user_id;
}
}
});
$scope.$broadcast('scroll.infiniteScrollComplete');
};
HTML
<ion-infinite-scroll on-infinite="addMoreItem()" distance="1%"> </ion-infinite-scroll>
And one thing is before the first record displays the chrome console read a lot of this error:Cannot read property 'push' of undefined and when the page is still it automatically reloads the same records again

Reload a content almost invisibly and no blinking effect using JAVASCRIPT

I'm writing a small progam wherein I'm getting data using $.get then display the data so far so good and then there's this part then when I click a certain link it refresh the page but it has this blinking effect. Is there a way on how to reload the content get the new updated content then replace the previously loaded data.
NOTE: I didn't use setInterval or setTimeout function because it slows down the process of my website. any answer that does not include those functions are really appreciated.
Here's the code
function EmployeeIssues(){
$('#initial_left').css({'display' : 'none'});
var table = $('#table_er');
$.get('admin/emp_with_issues', function(result){
var record = $.parseJSON(result);
var data = record.data,
employees = data.employees,
pages = data.pages;
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
for (var i = 0; i < employees.length; i++) {
$('#table_er').fadeIn('slow');
table.append(write_link(employees[i])); // function that displays the data
}
if(pages){
$('#pagination').html(pages);
}
}else{
$('#er_tab_label').html('<b>No employees with issues yet.</b>');
}
});
table.html('');
}
then this part calls the function and display another updated content
$('#refresh_btn').on('click', function(e){
e.preventDefault();
var tab = $('#tab').val();
if(tab == 'er'){
EmployeeIssues();
}
});
What should I do to display the content without any blinking effect?
thanks :-)
This section might be the issue :
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
for (var i = 0; i < employees.length; i++) {
$('#table_er').fadeIn('slow');
table.append(write_link(employees[i])); // function that displays the data
}
if(pages){
$('#pagination').html(pages);
}
} else ...
It seems you're asking table_er to fade in once per run of the loop whereas s there can only be one such table, you only need to do it once ?
first try re-arringing it like this:
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
$('#table_er').hide(); // hide it while we add the html
for (var i = 0; i < employees.length; i++) {
table.append(write_link(employees[i])); // function that displays the data
}
$('#table_er').fadeIn('slow'); // only do this after the table has all its html
if(pages){
$('#pagination').html(pages);
}
} else ....
Another possibility is that you're running through a loop and asking jquery to do stuff while the loop is running. It might be better to work out the whole HTML for the new page data in a string and then get the screen to render it in one line. I cna't do this for you as I don't know what's in write_link etc but something like this ..
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
var sHTML ="";
$('#table_er').hide(); // hide it while we add the html
for (var i = 0; i < employees.length; i++) {
sHTML+=write_link(employees[i]); // maybe this is right ? if write_link returns an HTML string ?
}
table.append(sHTML); // add the HTML from the string in one go - stops the page rendering while the code is running
$('#table_er').fadeIn('slow'); // now show the table.
if(pages){
$('#pagination').html(pages);
}
} else ...

Page hangs up, too much to search

I used PHP to create an HTML page, which compiles a list of data points and pushes them into an array, declares the array in the header, and also echo's a huge list of form input objects into the body.
The list I'm working with is just under 15,000 lines which are put into 1 array.
I more or less created a search box that when I blur() an action is supposed to occur, Javascript function is supposed to search through the array and hide unmatched form options and display matches. This seems to work fine up to 5000 but if I have it run through all 15000 array items it hangs up and freezes.
I'm currently hosting it on a free site while I test... here is the link to the actual page TEST PAGE that hangs up
I'm including a snippet of the JS code with a truncated array so you don't have to scroll for thousands of lines.
<script type="text/javascript" >
var array_ICDDx = new Array('[ICD Code] Diagnosis','[001.0] Cholera due to vibrio cholerae','[001.1] Cholera due to vibrio cholerae el tor','[001.9] Cholera, unspecified','[002.0] Typhoid fever','[002.1] Paratyphoid fever A','[002.2] Paratyphoid fever B','[002.3] Paratyphoid fever C','[002.9] Paratyphoid fever, unspecified','[003.0] Salmonella gastroenteritis','[003.1] Salmonella septicemia','[003.20] Localized salmonella infection, unspecified','[003.21] Salmonella meningitis','[003.22] Salmonella pneumonia','[003.23] Salmonella arthritis','[003.24] Salmonella osteomyelitis',[...GOES ON FOREVER ~15000 ARRAY VALUES...]);
function searchICDDx(ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
var ICDDx_check = array_ICDDx[a].toLowerCase();
var Row = "R" + a;
if (ICDDx_check.search(ICDDx) >= 0) {
document.getElementById(Row).style.display = "block";
}
else {
document.getElementById(Row).style.display = "none";
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
var timer = setTimeout(searchICDDx(ICDDx,a,line_end),100);
// searchICDDx(ICDDx,a,line_end);
}
// else if (line_end >= array_ICDDx.length) {
// clearTimeout(timer);
return;
// }
}
function searchICD() {
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(find_ICD,1,1000);
}
}
function searchDx() {
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(find_Dx,1,1000);
}
}
</script>
It doesn't appear to be an issue with the code not functioning. As I mentioned, if I limit the search to just 1000 array values it seems to work, its the massive amount of array values that is killing the page.
Any suggestions?
Thank you in advance!
With this many data points, you should probably do this on the server. However, you can try the following:
instead of using a for loop (which completely freezes the browser until it is done), use a setInterval that checks a new result every 5 ms or so. Periodically, check if all the results have been searched, and clear the interval if so. It will still take a bit to search, but won't freeze the browser.
search only until you have a set number of results (40 or so), and store the last index of the array that was searched. Wait to load more searches until the user scrolls down the page.
Also, you should probably implement an infinite scroll for displaying results. My browser froze and had to be restarted just opening the link you attached.
Update: if you don't want the items displayed until after you search, you should have no items on the page initially and add them when they match the search. This prevents the initial lag, prevents you from having to change the visibility of every element, and reduces the number of elements on the page (which causes issues).
Thank you for all your input and suggestions.
I went back and took out all of entries when listed in the form. Then I had JS create a list of checkbox inputs based on all the positive results and element.innerHTML the results. The array is still a huge list on client side through which the JS searches for matches. I updated the code in the link from my original post to show the faster and working result.
<script type="text/javascript" >
var array_ICDDx = new Array('[icd code] diagnosis','[001.0] cholera due to vibrio cholerae','[001.1] cholera due to vibrio cholerae el tor','[001.9] cholera, unspecified','[002.0] typhoid fever','[002.1] paratyphoid fever a',[...etc...]);
function searchICDDx(array_Results,ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
if (array_ICDDx[a].indexOf(ICDDx) >= 0) {
array_Results.push("<span style='display:block' ><input type='checkbox' value='"+array_ICDDx[a]+"' >"+array_ICDDx[a]+"</span>");
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
searchICDDx(array_Results,ICDDx,a,line_end);
}
else if (line_end >= array_ICDDx.length) {
var string_Results = array_Results.join("\n");
document.getElementById("Results_here").innerHTML = string_Results;
return;
}
}
function searchICD() {
var array_Results = new Array();
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(array_Results,find_ICD,1,1000);
}
}
function searchDx() {
var array_Results = new Array();
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(array_Results,find_Dx,1,1000);
}
}
</script>
In the past I've had poor results with forms and innerHTML added options, which I'll tackle another time when I try to move this code into the larger project.
Thank you again

Why is this jquery .each loop stopping my function call in the middle?

This is the entire function I am working on:
function collapse(){
var i = 0;
var currColors = [];
var currTitles = [];
// Get the color and the course id of all the current courses
$('.course').each(function (){
if (rgb2hex($(this).css("background-color")) !== "#f9f9f9") {
currColors.push(rgb2hex($(this).css("background-color")));
currTitles.push($(this).children(".course-id").text());
$(this).children(".course-delete").remove();
$(this).children(".course-id").text("");
$(this).css('background', "#f9f9f9");
}
});
alert("made it");
// Redistribute the classes
// This is where reverse lookup will eventually happen
i = 0;
$('div.course').each(function (){
if (i>=currTitles.length){
return false;
}
$(this).children(".course-id").text(currTitles[i]);
$(this).css('background', currColors[i++]);
$(this).append("<button id='temp' class='course-delete'>X</button>");
});
var i = currColors.length-1;
};
And this is the problematic section
$('.course').each(function (){
if (rgb2hex($(this).css("background-color")) !== "#f9f9f9") {
currColors.push(rgb2hex($(this).css("background-color")));
currTitles.push($(this).children(".course-id").text());
$(this).children(".course-delete").remove();
$(this).children(".course-id").text("");
$(this).css('background', "#f9f9f9");
}
});
I have this function collapse that is supposed to fill in the blank spot in a list of divs that the user has been adding to the screen if they delete one. This function was working fine at one point, but obviously I have screwed it up some how.
There are only and always will be 6 '.course' items because that is the size of the list. When collapse() is called it stops running after n times where n is the number of '.course' elements currently in use. The loop stops there and the whole function stops there. I have tried putting alert() statements everywhere but still no luck. If someone spots what I am missing I would really appreciate it.
I have figured out a work around for now, but I would like to know why my entire function is crashing in the middle.

Categories

Resources